Asterisk - The Open Source Telephony Project  GIT-master-a24979a
Data Structures | Macros | Enumerations | Functions | Variables
pbx_dundi.c File Reference

Distributed Universal Number Discovery (DUNDi) More...

#include "asterisk.h"
#include "asterisk/network.h"
#include <sys/ioctl.h>
#include <zlib.h>
#include <signal.h>
#include <pthread.h>
#include <net/if.h>
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/config.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/netsock2.h"
#include "asterisk/crypto.h"
#include "asterisk/astdb.h"
#include "asterisk/acl.h"
#include "asterisk/app.h"
#include "dundi-parser.h"
Include dependency graph for pbx_dundi.c:

Go to the source code of this file.

Data Structures

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

Macros

#define DUNDI_FLAG_INTERNAL_NOPARTIAL   (1 << 17)
 
#define DUNDI_MODEL_INBOUND   (1 << 0)
 
#define DUNDI_MODEL_OUTBOUND   (1 << 1)
 
#define DUNDI_MODEL_SYMMETRIC   (DUNDI_MODEL_INBOUND | DUNDI_MODEL_OUTBOUND)
 
#define DUNDI_SECRET_TIME   DUNDI_DEFAULT_CACHE_TIME
 
#define DUNDI_TIMING_HISTORY   10
 
#define FORMAT   "%-20.20s %-41s %s %-6d %-10.10s %-8.8s %-15.15s\n"
 
#define FORMAT   "%-41s:%5d %-5.5d %-5.5d %-3.3d %-3.3d %-3.3d\n"
 
#define FORMAT   "%-15s %-15s %-15s %-3.3d %-3.3d\n"
 
#define FORMAT   "%-12.12s %-7s %-12.12s %-10.10s %-5.5s %-25.25s\n"
 
#define FORMAT   "%-12.12s %-12.12s %02d:%02d:%02d\n"
 
#define FORMAT   "%-12.12s %-16.16s %6d sec %-18s %-7d %s/%s (%s)\n"
 
#define FORMAT   "%-12.12s %-16.16s %6d sec %-18s\n"
 
#define FORMAT2   "%-20.20s %-41s %-6.6s %-10.10s %-8.8s %-15.15s\n"
 
#define FORMAT2   "%-47s %-5.5s %-5.5s %-3.3s %-3.3s %-3.3s\n"
 
#define FORMAT2   "%-15s %-15s %-15s %-3.3s %-3.3s\n"
 
#define FORMAT2   "%-12.12s %-7.7s %-12.12s %-10.10s %-5.5s %-25.25s\n"
 
#define FORMAT2   "%-12.12s %-12.12s %-10.10s\n"
 
#define FORMAT2   "%-12.12s %-16.16s %-10.10s %-18s %-7s %s\n"
 
#define FORMAT2   "%-12.12s %-16.16s %-10.10s %-18s\n"
 
#define MAX_OPTS   128
 
#define MAX_PACKET_SIZE   8192
 
#define MAX_RESULTS   64
 
#define MAX_WEIGHT   59999
 

Enumerations

enum  {
  FLAG_ISREG = (1 << 0) , FLAG_DEAD = (1 << 1) , FLAG_FINAL = (1 << 2) , FLAG_ISQUAL = (1 << 3) ,
  FLAG_ENCRYPT = (1 << 4) , FLAG_SENDFULLKEY = (1 << 5) , FLAG_STOREHIST = (1 << 6)
}
 
enum  { OPT_BYPASS_CACHE = (1 << 0) }
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static void abort_request (struct dundi_request *dr)
 
static int ack_trans (struct dundi_transaction *trans, int iseqno)
 
static void append_permission (struct permissionlist *permlist, const 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)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static unsigned long avoid_crc32 (dundi_eid *avoid[])
 
static void build_iv (unsigned char *iv)
 
static void build_mapping (const char *name, const char *value)
 
static void build_peer (dundi_eid *eid, struct ast_variable *v, int *globalpcmode)
 
static void build_secret (char *secret, int seclen)
 
static void build_transactions (struct dundi_request *dr, int ttl, int order, int *foundcache, int *skipped, int blockempty, int nocache, int modeselect, dundi_eid *skip, dundi_eid *avoid[], int directs[])
 
static int cache_lookup (struct dundi_request *req, dundi_eid *peer_eid, uint32_t crc, int *lowexpiration)
 
static int cache_lookup_internal (time_t now, struct dundi_request *req, char *key, char *eid_str_full, int *lowexpiration)
 
static int cache_save (dundi_eid *eidpeer, struct dundi_request *req, int start, int unaffected, int expiration, int push)
 
static int cache_save_hint (dundi_eid *eidpeer, struct dundi_request *req, struct dundi_hint *hint, int expiration)
 
static void cancel_request (struct dundi_request *dr)
 
static int check_key (struct dundi_peer *peer, unsigned char *newkey, unsigned char *newsig, uint32_t keycrc32)
 
static void check_password (void)
 
static int check_request (struct dundi_request *dr)
 
static char * complete_peer_helper (const char *line, const char *word, int pos, int state, int rpos)
 
static struct dundi_transactioncreate_transaction (struct dundi_peer *p)
 
static int decrypt_memcpy (unsigned char *dst, unsigned char *src, int len, unsigned char *iv, ast_aes_decrypt_key *dcx)
 
static void deep_copy_peer (struct dundi_peer *peer_dst, const struct dundi_peer *peer_src)
 
static void destroy_map (struct dundi_mapping *map)
 
static void destroy_packet (struct dundi_packet *pack, int needfree)
 
static void destroy_packets (struct packetlist *p)
 
static void destroy_peer (struct dundi_peer *peer)
 
static void destroy_permissions (struct permissionlist *permlist)
 
static void destroy_trans (struct dundi_transaction *trans, int fromtimeout)
 
static int discover_transactions (struct dundi_request *dr)
 
static int do_autokill (const void *data)
 
static int do_qualify (const void *data)
 
static int do_register (const void *data)
 
static int do_register_expire (const void *data)
 
static void drds_destroy (struct dundi_result_datastore *drds)
 
static void drds_destroy_cb (void *data)
 
static int dundi_ack (struct dundi_transaction *trans, int final)
 
static int dundi_answer_entity (struct dundi_transaction *trans, struct dundi_ies *ies, char *ccontext)
 
static int dundi_answer_query (struct dundi_transaction *trans, struct dundi_ies *ies, char *ccontext)
 
static int dundi_canmatch (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
 
static void dundi_debug_output (const char *data)
 
static struct dundi_hdrdundi_decrypt (struct dundi_transaction *trans, unsigned char *dst, int *dstlen, struct dundi_hdr *ohdr, struct dundi_encblock *src, int srclen)
 
static int dundi_discover (struct dundi_transaction *trans)
 
static char * dundi_do_lookup (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * dundi_do_precache (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * dundi_do_query (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int dundi_encrypt (struct dundi_transaction *trans, struct dundi_packet *pack)
 
static void dundi_error_output (const char *data)
 
static int dundi_exec (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
 
static int dundi_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
 
static char * dundi_flush (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
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. Lookup number in a given dundi context (if unspecified use e164), the given callerid (if specified) and return up to maxret results in the array specified. More...
 
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)
 
int dundi_precache (const char *context, const char *number)
 Pre-cache to push upstream peers. More...
 
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. More...
 
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 int dundi_query_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 
static void * dundi_query_thread (void *data)
 
static void dundi_reject (struct dundi_hdr *h, struct ast_sockaddr *sin)
 
static int dundi_result_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 
static int dundi_rexmit (const void *data)
 
static int dundi_send (struct dundi_transaction *trans, int cmdresp, int flags, int final, struct dundi_ie_data *ied)
 
static char * dundi_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * dundi_show_cache (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * dundi_show_entityid (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * dundi_show_hints (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * dundi_show_mappings (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * dundi_show_peer (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * dundi_show_peers (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * dundi_show_precache (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * dundi_show_requests (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * dundi_show_trans (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static uint16_t dundi_sockaddr_port (const struct ast_sockaddr *addr)
 
static char * dundi_sockaddr_stringify_host (const struct ast_sockaddr *addr)
 
static char * dundi_store_history (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int dundi_xmit (struct dundi_packet *pack)
 
static int dundifunc_read (struct ast_channel *chan, const char *cmd, char *num, char *buf, size_t len)
 
static int encrypt_memcpy (unsigned char *dst, unsigned char *src, int len, unsigned char *iv, ast_aes_encrypt_key *ecx)
 
static struct dundi_peerfind_peer (dundi_eid *eid)
 
static struct dundi_transactionfind_transaction (struct dundi_hdr *hdr, struct ast_sockaddr *sin)
 
static int get_ipaddress (char *ip, size_t size, const char *str, int family)
 
static int get_mapping_weight (struct dundi_mapping *map, struct varshead *headp)
 
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 ast_sockaddr *sin, int datalen)
 
static int has_permission (struct permissionlist *permlist, char *cont)
 
static int load_module (void)
 
static void load_password (void)
 
static void mark_mappings (void)
 
static void mark_peers (void)
 
static char * model2str (int model)
 
static void * network_thread (void *ignore)
 
static int optimize_transactions (struct dundi_request *dr, int order)
 
static void populate_addr (struct dundi_peer *peer, dundi_eid *eid)
 
static int precache_trans (struct dundi_transaction *trans, struct dundi_mapping *maps, int mapcount, int *minexp, int *foundanswers)
 
static int precache_transactions (struct dundi_request *dr, struct dundi_mapping *maps, int mapcount, int *expiration, int *foundanswers)
 
static void * process_clearcache (void *ignore)
 
static void * process_precache (void *ign)
 
static void prune_mappings (void)
 
static void prune_peers (void)
 
static void qualify_peer (struct dundi_peer *peer, int schedonly)
 
static int query_transactions (struct dundi_request *dr)
 
static int register_request (struct dundi_request *dr, struct dundi_request **pending)
 
static int reload (void)
 
static void reschedule_precache (const char *number, const char *context, int expiration)
 
static int rescomp (const void *a, const void *b)
 
static 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 ast_sockaddr *sin, int reload, struct ast_sockaddr *sin2)
 
static void set_host_ipaddr (struct ast_sockaddr *sin)
 
static int socket_read (int *id, int fd, short events, void *sock)
 
static void sort_results (struct dundi_result *results, int count)
 
static int start_network_thread (void)
 
static int str2tech (char *str)
 
static char * tech2str (int tech)
 
static int unload_module (void)
 
static void unregister_request (struct dundi_request *dr)
 
static int update_key (struct dundi_peer *peer)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Distributed Universal Number Discovery (DUNDi)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .optional_modules = "res_crypto", }
 
static struct alltrans alltrans = { .first = NULL, .last = NULL, }
 
static struct dundi_peerany_peer
 Wildcard peer. More...
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static int authdebug = 0
 
static pthread_t clearcachethreadid = AST_PTHREADT_NULL
 
static struct ast_cli_entry cli_dundi []
 
static char country [80]
 
static char cursecret [80]
 
static int default_expiration = 60
 
static char dept [80]
 
static int dundi_cache_time = DUNDI_DEFAULT_CACHE_TIME
 
static struct ast_custom_function dundi_function
 
static int dundi_key_ttl = DUNDI_DEFAULT_KEY_EXPIRE
 
static struct ast_custom_function dundi_query_function
 
static const struct ast_app_option dundi_query_opts [128] = { [ 'b' ] = { .flag = OPT_BYPASS_CACHE }, }
 
static const struct ast_datastore_info dundi_result_datastore_info
 
static struct ast_custom_function dundi_result_function
 
static unsigned int dundi_result_id
 
static int dundi_shutdown = 0
 
static struct ast_switch dundi_switch
 
static int dundi_ttl = DUNDI_DEFAULT_TTL
 
static int dundidebug = 0
 
static char email [80]
 
static dundi_eid empty_eid = { { 0, 0, 0, 0, 0, 0 } }
 
static int global_autokilltimeout = 0
 
static dundi_eid global_eid
 
static int global_storehistory = 0
 
static struct io_contextio
 
static char ipaddr [80]
 
static char locality [80]
 
static struct mappings mappings = { .first = NULL, .last = NULL, }
 
static int netsocket = -1
 
static int netsocket2 = -1
 
static pthread_t netthreadid = AST_PTHREADT_NULL
 
static char org [80]
 
static struct pcq pcq = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
 
static struct peers peers = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
 
static char phone [80]
 
static pthread_t precachethreadid = AST_PTHREADT_NULL
 
static struct requests requests = { .first = NULL, .last = NULL, }
 
static time_t rotatetime
 
static struct ast_sched_contextsched
 
static char secretpath [80]
 
static char stateprov [80]
 
static unsigned int tos = 0
 

Detailed Description

Distributed Universal Number Discovery (DUNDi)

Definition in file pbx_dundi.c.

Macro Definition Documentation

◆ DUNDI_FLAG_INTERNAL_NOPARTIAL

#define DUNDI_FLAG_INTERNAL_NOPARTIAL   (1 << 17)

Definition at line 176 of file pbx_dundi.c.

◆ DUNDI_MODEL_INBOUND

#define DUNDI_MODEL_INBOUND   (1 << 0)

Definition at line 159 of file pbx_dundi.c.

◆ DUNDI_MODEL_OUTBOUND

#define DUNDI_MODEL_OUTBOUND   (1 << 1)

Definition at line 160 of file pbx_dundi.c.

◆ DUNDI_MODEL_SYMMETRIC

#define DUNDI_MODEL_SYMMETRIC   (DUNDI_MODEL_INBOUND | DUNDI_MODEL_OUTBOUND)

Definition at line 161 of file pbx_dundi.c.

◆ DUNDI_SECRET_TIME

#define DUNDI_SECRET_TIME   DUNDI_DEFAULT_CACHE_TIME

Definition at line 181 of file pbx_dundi.c.

◆ DUNDI_TIMING_HISTORY

#define DUNDI_TIMING_HISTORY   10

Keep times of last 10 lookups

Definition at line 164 of file pbx_dundi.c.

◆ FORMAT [1/7]

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

◆ FORMAT [2/7]

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

◆ FORMAT [3/7]

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

◆ FORMAT [4/7]

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

◆ FORMAT [5/7]

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

◆ FORMAT [6/7]

#define FORMAT   "%-12.12s %-16.16s %6d sec %-18s %-7d %s/%s (%s)\n"

◆ FORMAT [7/7]

#define FORMAT   "%-12.12s %-16.16s %6d sec %-18s\n"

◆ FORMAT2 [1/7]

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

◆ FORMAT2 [2/7]

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

◆ FORMAT2 [3/7]

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

◆ FORMAT2 [4/7]

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

◆ FORMAT2 [5/7]

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

◆ FORMAT2 [6/7]

#define FORMAT2   "%-12.12s %-16.16s %-10.10s %-18s %-7s %s\n"

◆ FORMAT2 [7/7]

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

◆ MAX_OPTS

#define MAX_OPTS   128

Definition at line 4455 of file pbx_dundi.c.

◆ MAX_PACKET_SIZE

#define MAX_PACKET_SIZE   8192

Definition at line 155 of file pbx_dundi.c.

◆ MAX_RESULTS

#define MAX_RESULTS   64

Definition at line 153 of file pbx_dundi.c.

◆ MAX_WEIGHT

#define MAX_WEIGHT   59999

Definition at line 157 of file pbx_dundi.c.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
FLAG_ISREG 

Transaction is register request

FLAG_DEAD 

Transaction is dead

FLAG_FINAL 

Transaction has final message sent

FLAG_ISQUAL 

Transaction is a qualification

FLAG_ENCRYPT 

Transaction is encrypted with ECX/DCX

FLAG_SENDFULLKEY 

Send full key on transaction

FLAG_STOREHIST 

Record historic performance

Definition at line 166 of file pbx_dundi.c.

166  {
167  FLAG_ISREG = (1 << 0), /*!< Transaction is register request */
168  FLAG_DEAD = (1 << 1), /*!< Transaction is dead */
169  FLAG_FINAL = (1 << 2), /*!< Transaction has final message sent */
170  FLAG_ISQUAL = (1 << 3), /*!< Transaction is a qualification */
171  FLAG_ENCRYPT = (1 << 4), /*!< Transaction is encrypted with ECX/DCX */
172  FLAG_SENDFULLKEY = (1 << 5), /*!< Send full key on transaction */
173  FLAG_STOREHIST = (1 << 6), /*!< Record historic performance */
174 };
@ FLAG_ISQUAL
Definition: pbx_dundi.c:170
@ FLAG_DEAD
Definition: pbx_dundi.c:168
@ FLAG_SENDFULLKEY
Definition: pbx_dundi.c:172
@ FLAG_FINAL
Definition: pbx_dundi.c:169
@ FLAG_ISREG
Definition: pbx_dundi.c:167
@ FLAG_ENCRYPT
Definition: pbx_dundi.c:171
@ FLAG_STOREHIST
Definition: pbx_dundi.c:173

◆ anonymous enum

anonymous enum
Enumerator
OPT_BYPASS_CACHE 

Definition at line 4129 of file pbx_dundi.c.

4129  {
4130  OPT_BYPASS_CACHE = (1 << 0),
4131 };
@ OPT_BYPASS_CACHE
Definition: pbx_dundi.c:4130

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 5278 of file pbx_dundi.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 5278 of file pbx_dundi.c.

◆ abort_request()

static void abort_request ( struct dundi_request dr)
static

Definition at line 3688 of file pbx_dundi.c.

3689 {
3690  struct dundi_transaction *trans;
3691 
3692  AST_LIST_LOCK(&peers);
3693  while ((trans = AST_LIST_FIRST(&dr->trans))) {
3694  /* This will remove the transaction from the list */
3695  destroy_trans(trans, 0);
3696  }
3698 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:40
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:421
static void destroy_trans(struct dundi_transaction *trans, int fromtimeout)
Definition: pbx_dundi.c:3203
static float dr[4]
Definition: tdd.c:58

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

Referenced by dundi_lookup_internal().

◆ ack_trans()

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

Definition at line 2021 of file pbx_dundi.c.

2022 {
2023  struct dundi_packet *pack;
2024 
2025  /* Ack transmitted packet corresponding to iseqno */
2026  AST_LIST_TRAVERSE(&trans->packets, pack, list) {
2027  if ((pack->h->oseqno + 1) % 255 == iseqno) {
2028  destroy_packet(pack, 0);
2029  if (!AST_LIST_EMPTY(&trans->lasttrans)) {
2030  ast_log(LOG_WARNING, "Whoa, there was still a last trans?\n");
2031  destroy_packets(&trans->lasttrans);
2032  }
2033  AST_LIST_INSERT_HEAD(&trans->lasttrans, pack, list);
2034  AST_SCHED_DEL(sched, trans->autokillid);
2035  return 1;
2036  }
2037  }
2038 
2039  return 0;
2040 }
#define ast_log
Definition: astobj2.c:42
#define LOG_WARNING
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:450
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:711
static void destroy_packets(struct packetlist *p)
Definition: pbx_dundi.c:2010
static void destroy_packet(struct dundi_packet *pack, int needfree)
Definition: pbx_dundi.c:3194
#define AST_SCHED_DEL(sched, id)
Remove a scheduler entry.
Definition: sched.h:46
unsigned char oseqno
Definition: dundi.h:38
struct dundi_packet::@438 list
struct dundi_hdr * h
Definition: pbx_dundi.c:223
struct dundi_transaction::packetlist packets
struct packetlist lasttrans
Definition: pbx_dundi.c:267
Definition: sched.c:76

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

Referenced by handle_frame().

◆ append_permission()

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

Definition at line 4442 of file pbx_dundi.c.

4443 {
4444  struct permission *perm;
4445 
4446  if (!(perm = ast_calloc(1, sizeof(*perm) + strlen(s) + 1)))
4447  return;
4448 
4449  strcpy(perm->name, s);
4450  perm->allow = allow;
4451 
4452  AST_LIST_INSERT_TAIL(permlist, perm, list);
4453 }
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
struct permission::@437 list
char name[0]
Definition: pbx_dundi.c:218

References permission::allow, ast_calloc, AST_LIST_INSERT_TAIL, permission::list, and permission::name.

Referenced by build_peer().

◆ append_transaction()

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

Definition at line 3642 of file pbx_dundi.c.

3643 {
3644  struct dundi_transaction *trans;
3645  int x;
3646  char eid_str[20];
3647  char eid_str2[20];
3648 
3649  /* Ignore if not registered */
3650  if (ast_sockaddr_isnull(&p->addr)) {
3651  return 0;
3652  }
3653  if (p->maxms && ((p->lastms < 0) || (p->lastms >= p->maxms)))
3654  return 0;
3655 
3656  if (ast_strlen_zero(dr->number))
3657  ast_debug(1, "Will query peer '%s' for '%s' (context '%s')\n", ast_eid_to_str(eid_str, sizeof(eid_str), &p->eid), ast_eid_to_str(eid_str2, sizeof(eid_str2), &dr->query_eid), dr->dcontext);
3658  else
3659  ast_debug(1, "Will query peer '%s' for '%s@%s'\n", ast_eid_to_str(eid_str, sizeof(eid_str), &p->eid), dr->number, dr->dcontext);
3660 
3661  trans = create_transaction(p);
3662  if (!trans)
3663  return -1;
3664  trans->parent = dr;
3665  trans->ttl = ttl;
3666  for (x = 0; avoid[x] && (x < DUNDI_MAX_STACK); x++)
3667  trans->eids[x] = *avoid[x];
3668  trans->eidcount = x;
3669  AST_LIST_INSERT_HEAD(&dr->trans, trans, parentlist);
3670 
3671  return 0;
3672 }
#define DUNDI_MAX_STACK
Definition: dundi-parser.h:18
#define ast_debug(level,...)
Log a DEBUG message.
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized,...
Definition: netsock2.h:127
static struct dundi_transaction * create_transaction(struct dundi_peer *p)
Definition: pbx_dundi.c:3137
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
struct ast_sockaddr addr
Definition: pbx_dundi.c:305
int lastms
Definition: pbx_dundi.c:335
dundi_eid eid
Definition: pbx_dundi.c:304
struct dundi_transaction::@440 parentlist
dundi_eid eids[DUNDI_MAX_STACK+1]
Definition: pbx_dundi.c:248
struct dundi_request * parent
Definition: pbx_dundi.c:268
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
Definition: main/utils.c:2735

References dundi_peer::addr, ast_debug, ast_eid_to_str(), AST_LIST_INSERT_HEAD, ast_sockaddr_isnull(), ast_strlen_zero(), create_transaction(), dr, DUNDI_MAX_STACK, dundi_peer::eid, dundi_transaction::eidcount, dundi_transaction::eids, dundi_peer::lastms, dundi_peer::maxms, dundi_transaction::parent, dundi_transaction::parentlist, and dundi_transaction::ttl.

Referenced by build_transactions().

◆ apply_peer()

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

Definition at line 1295 of file pbx_dundi.c.

1296 {
1297  if (ast_sockaddr_isnull(&trans->addr)) {
1298  ast_sockaddr_copy(&trans->addr, &p->addr);
1299  }
1300  trans->us_eid = p->us_eid;
1301  trans->them_eid = p->eid;
1302  /* Enable encryption if appropriate */
1303  if (!ast_strlen_zero(p->inkey))
1304  ast_set_flag(trans, FLAG_ENCRYPT);
1305  if (p->maxms) {
1306  trans->autokilltimeout = p->maxms;
1308  if (p->lastms > 1) {
1309  trans->retranstimer = p->lastms * 2;
1310  /* Keep it from being silly */
1311  if (trans->retranstimer < 150)
1312  trans->retranstimer = 150;
1313  }
1316  } else
1318 }
#define DUNDI_DEFAULT_RETRANS_TIMER
Definition: dundi.h:215
static void ast_sockaddr_copy(struct ast_sockaddr *dst, const struct ast_sockaddr *src)
Copies the data from one ast_sockaddr to another.
Definition: netsock2.h:167
static int global_autokilltimeout
Definition: pbx_dundi.c:197
dundi_eid us_eid
Definition: pbx_dundi.c:308
char inkey[80]
Definition: pbx_dundi.c:309
struct ast_sockaddr addr
Definition: pbx_dundi.c:246
dundi_eid us_eid
Definition: pbx_dundi.c:250
dundi_eid them_eid
Definition: pbx_dundi.c:251
#define ast_set_flag(p, flag)
Definition: utils.h:70

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

Referenced by create_transaction(), and handle_command_response().

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 5278 of file pbx_dundi.c.

◆ avoid_crc32()

static unsigned long avoid_crc32 ( dundi_eid avoid[])
static

Definition at line 3809 of file pbx_dundi.c.

3810 {
3811  /* Idea is that we're calculating a checksum which is independent of
3812  the order that the EID's are listed in */
3813  uint32_t acrc32 = 0;
3814  int x;
3815  for (x=0;avoid[x];x++) {
3816  /* Order doesn't matter */
3817  if (avoid[x+1]) {
3818  acrc32 ^= crc32(0L, (unsigned char *)avoid[x], sizeof(dundi_eid));
3819  }
3820  }
3821  return acrc32;
3822 }
An Entity ID is essentially a MAC address, brief and unique.
Definition: utils.h:808

References dundi_request::crc32.

Referenced by dundi_lookup_internal().

◆ build_iv()

static void build_iv ( unsigned char *  iv)
static

Definition at line 533 of file pbx_dundi.c.

534 {
535  /* XXX Would be nice to be more random XXX */
536  unsigned int *fluffy;
537  int x;
538  fluffy = (unsigned int *)(iv);
539  for (x=0;x<4;x++)
540  fluffy[x] = ast_random();
541 }
long int ast_random(void)
Definition: main/utils.c:2210

References ast_random().

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

◆ build_mapping()

static void build_mapping ( const char *  name,
const char *  value 
)
static

Definition at line 4457 of file pbx_dundi.c.

4458 {
4459  char *t, *fields[MAX_OPTS];
4460  struct dundi_mapping *map;
4461  int x;
4462  int y;
4463 
4464  t = ast_strdupa(value);
4465 
4466  AST_LIST_TRAVERSE(&mappings, map, list) {
4467  /* Find a double match */
4468  if (!strcasecmp(map->dcontext, name) &&
4469  (!strncasecmp(map->lcontext, value, strlen(map->lcontext)) &&
4470  (!value[strlen(map->lcontext)] ||
4471  (value[strlen(map->lcontext)] == ','))))
4472  break;
4473  }
4474  if (!map) {
4475  if (!(map = ast_calloc(1, sizeof(*map))))
4476  return;
4478  map->dead = 1;
4479  }
4480  map->options = 0;
4481  memset(fields, 0, sizeof(fields));
4482  x = 0;
4483  while (t && x < MAX_OPTS) {
4484  fields[x++] = t;
4485  t = strchr(t, ',');
4486  if (t) {
4487  *t = '\0';
4488  t++;
4489  }
4490  } /* Russell was here, arrrr! */
4491  if ((x == 1) && ast_strlen_zero(fields[0])) {
4492  /* Placeholder mapping */
4493  ast_copy_string(map->dcontext, name, sizeof(map->dcontext));
4494  map->dead = 0;
4495  } else if (x >= 4) {
4496  ast_copy_string(map->dcontext, name, sizeof(map->dcontext));
4497  ast_copy_string(map->lcontext, fields[0], sizeof(map->lcontext));
4498  if ((sscanf(fields[1], "%30d", &map->_weight) == 1) && (map->_weight >= 0) && (map->_weight <= MAX_WEIGHT)) {
4499  ast_copy_string(map->dest, fields[3], sizeof(map->dest));
4500  if ((map->tech = str2tech(fields[2])))
4501  map->dead = 0;
4502  } else if (!strncmp(fields[1], "${", 2) && fields[1][strlen(fields[1]) - 1] == '}') {
4503  map->weightstr = ast_strdup(fields[1]);
4504  ast_copy_string(map->dest, fields[3], sizeof(map->dest));
4505  if ((map->tech = str2tech(fields[2])))
4506  map->dead = 0;
4507  } else {
4508  ast_log(LOG_WARNING, "Invalid weight '%s' specified, deleting entry '%s/%s'\n", fields[1], map->dcontext, map->lcontext);
4509  }
4510  for (y = 4;y < x; y++) {
4511  if (!strcasecmp(fields[y], "nounsolicited"))
4513  else if (!strcasecmp(fields[y], "nocomunsolicit"))
4515  else if (!strcasecmp(fields[y], "residential"))
4517  else if (!strcasecmp(fields[y], "commercial"))
4519  else if (!strcasecmp(fields[y], "mobile"))
4520  map->options |= DUNDI_FLAG_MOBILE;
4521  else if (!strcasecmp(fields[y], "nopartial"))
4523  else
4524  ast_log(LOG_WARNING, "Don't know anything about option '%s'\n", fields[y]);
4525  }
4526  } else
4527  ast_log(LOG_WARNING, "Expected at least %d arguments in map, but got only %d\n", 4, x);
4528 }
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
@ DUNDI_FLAG_MOBILE
Definition: dundi.h:80
@ DUNDI_FLAG_COMMERCIAL
Definition: dundi.h:78
@ DUNDI_FLAG_NOCOMUNSOLICIT
Definition: dundi.h:84
@ DUNDI_FLAG_RESIDENTIAL
Definition: dundi.h:76
@ DUNDI_FLAG_NOUNSOLICITED
Definition: dundi.h:82
static const char name[]
Definition: format_mp3.c:68
#define DUNDI_FLAG_INTERNAL_NOPARTIAL
Definition: pbx_dundi.c:176
static int str2tech(char *str)
Definition: pbx_dundi.c:396
#define MAX_WEIGHT
Definition: pbx_dundi.c:157
#define MAX_OPTS
Definition: pbx_dundi.c:4455
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:406
char lcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:293
struct dundi_mapping::@444 list
char * weightstr
Definition: pbx_dundi.c:295
char dest[512]
Definition: pbx_dundi.c:299
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:292
int value
Definition: syslog.c:37

References dundi_mapping::_weight, ast_calloc, ast_copy_string(), AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, ast_log, ast_strdup, 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, dundi_mapping::list, LOG_WARNING, MAX_OPTS, MAX_WEIGHT, name, dundi_mapping::options, str2tech(), dundi_mapping::tech, value, and dundi_mapping::weightstr.

Referenced by set_config().

◆ build_peer()

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

Definition at line 4628 of file pbx_dundi.c.

4629 {
4630  struct dundi_peer *peer;
4631  dundi_eid testeid;
4632  int needregister=0;
4633  char eid_str[20];
4634  int port = 0;
4635 
4636  AST_LIST_LOCK(&peers);
4637  AST_LIST_TRAVERSE(&peers, peer, list) {
4638  if (!ast_eid_cmp(&peer->eid, eid)) {
4639  break;
4640  }
4641  }
4642  if (!peer) {
4643  /* Add us into the list */
4644  if (!(peer = ast_calloc(1, sizeof(*peer)))) {
4646  return;
4647  }
4648  peer->registerid = -1;
4649  peer->registerexpire = -1;
4650  peer->qualifyid = -1;
4651  populate_addr(peer, eid);
4652  AST_LIST_INSERT_HEAD(&peers, peer, list);
4653  }
4654  peer->dead = 0;
4655  peer->eid = *eid;
4656  peer->us_eid = global_eid;
4657  destroy_permissions(&peer->permit);
4658  destroy_permissions(&peer->include);
4659  AST_SCHED_DEL(sched, peer->registerid);
4660  for (; v; v = v->next) {
4661  if (!strcasecmp(v->name, "inkey")) {
4662  ast_copy_string(peer->inkey, v->value, sizeof(peer->inkey));
4663  } else if (!strcasecmp(v->name, "outkey")) {
4664  ast_copy_string(peer->outkey, v->value, sizeof(peer->outkey));
4665  } else if (!strcasecmp(v->name, "port")) {
4666  port = atoi(v->value);
4667  } else if (!strcasecmp(v->name, "host")) {
4668  if (!strcasecmp(v->value, "dynamic")) {
4669  peer->dynamic = 1;
4670  } else {
4671  struct ast_sockaddr *addrs;
4672 
4673  if (ast_sockaddr_resolve(&addrs, v->value, PARSE_PORT_FORBID, AF_UNSPEC) > 0) {
4674  ast_sockaddr_copy(&peer->addr, &addrs[0]);
4675  peer->dynamic = 0;
4676  ast_free(addrs);
4677  } else {
4678  ast_log(LOG_WARNING, "Unable to find host '%s' at line %d\n", v->value, v->lineno);
4679  peer->dead = 1;
4680  }
4681  }
4682  } else if (!strcasecmp(v->name, "ustothem")) {
4683  if (!ast_str_to_eid(&testeid, v->value))
4684  peer->us_eid = testeid;
4685  else
4686  ast_log(LOG_WARNING, "'%s' is not a valid DUNDi Entity Identifier at line %d\n", v->value, v->lineno);
4687  } else if (!strcasecmp(v->name, "include")) {
4688  append_permission(&peer->include, v->value, 1);
4689  } else if (!strcasecmp(v->name, "permit")) {
4690  append_permission(&peer->permit, v->value, 1);
4691  } else if (!strcasecmp(v->name, "noinclude")) {
4692  append_permission(&peer->include, v->value, 0);
4693  } else if (!strcasecmp(v->name, "deny")) {
4694  append_permission(&peer->permit, v->value, 0);
4695  } else if (!strcasecmp(v->name, "register")) {
4696  needregister = ast_true(v->value);
4697  } else if (!strcasecmp(v->name, "order")) {
4698  if (!strcasecmp(v->value, "primary"))
4699  peer->order = 0;
4700  else if (!strcasecmp(v->value, "secondary"))
4701  peer->order = 1;
4702  else if (!strcasecmp(v->value, "tertiary"))
4703  peer->order = 2;
4704  else if (!strcasecmp(v->value, "quartiary"))
4705  peer->order = 3;
4706  else {
4707  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);
4708  }
4709  } else if (!strcasecmp(v->name, "qualify")) {
4710  if (!strcasecmp(v->value, "no")) {
4711  peer->maxms = 0;
4712  } else if (!strcasecmp(v->value, "yes")) {
4713  peer->maxms = DEFAULT_MAXMS;
4714  } else if (sscanf(v->value, "%30d", &peer->maxms) != 1) {
4715  ast_log(LOG_WARNING, "Qualification of peer '%s' should be 'yes', 'no', or a number of milliseconds at line %d of dundi.conf\n",
4716  ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), v->lineno);
4717  peer->maxms = 0;
4718  }
4719  } else if (!strcasecmp(v->name, "model")) {
4720  if (!strcasecmp(v->value, "inbound"))
4721  peer->model = DUNDI_MODEL_INBOUND;
4722  else if (!strcasecmp(v->value, "outbound"))
4723  peer->model = DUNDI_MODEL_OUTBOUND;
4724  else if (!strcasecmp(v->value, "symmetric"))
4725  peer->model = DUNDI_MODEL_SYMMETRIC;
4726  else if (!strcasecmp(v->value, "none"))
4727  peer->model = 0;
4728  else {
4729  ast_log(LOG_WARNING, "Unknown model '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n",
4730  v->value, v->lineno);
4731  }
4732  } else if (!strcasecmp(v->name, "precache")) {
4733  if (!strcasecmp(v->value, "inbound"))
4734  peer->pcmodel = DUNDI_MODEL_INBOUND;
4735  else if (!strcasecmp(v->value, "outbound"))
4736  peer->pcmodel = DUNDI_MODEL_OUTBOUND;
4737  else if (!strcasecmp(v->value, "symmetric"))
4739  else if (!strcasecmp(v->value, "none"))
4740  peer->pcmodel = 0;
4741  else {
4742  ast_log(LOG_WARNING, "Unknown pcmodel '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n",
4743  v->value, v->lineno);
4744  }
4745  }
4746  }
4747 
4748  if (!ast_sockaddr_isnull(&peer->addr)) {
4749  ast_sockaddr_set_port(&peer->addr, (0 < port) ? port : DUNDI_PORT);
4750  }
4751 
4752  (*globalpcmode) |= peer->pcmodel;
4753  if (!peer->model && !peer->pcmodel) {
4754  ast_log(LOG_WARNING, "Peer '%s' lacks a model or pcmodel, discarding!\n",
4755  ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
4756  peer->dead = 1;
4757  } else if ((peer->model & DUNDI_MODEL_INBOUND) && (peer->pcmodel & DUNDI_MODEL_OUTBOUND)) {
4758  ast_log(LOG_WARNING, "Peer '%s' may not be both inbound/symmetric model and outbound/symmetric precache model, discarding!\n",
4759  ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
4760  peer->dead = 1;
4761  } else if ((peer->model & DUNDI_MODEL_OUTBOUND) && (peer->pcmodel & DUNDI_MODEL_INBOUND)) {
4762  ast_log(LOG_WARNING, "Peer '%s' may not be both outbound/symmetric model and inbound/symmetric precache model, discarding!\n",
4763  ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
4764  peer->dead = 1;
4765  } else if (!AST_LIST_EMPTY(&peer->include) && !(peer->model & DUNDI_MODEL_OUTBOUND) && !(peer->pcmodel & DUNDI_MODEL_INBOUND)) {
4766  ast_log(LOG_WARNING, "Peer '%s' is supposed to be included in outbound searches but isn't an outbound peer or inbound precache!\n",
4767  ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
4768  } else if (!AST_LIST_EMPTY(&peer->permit) && !(peer->model & DUNDI_MODEL_INBOUND) && !(peer->pcmodel & DUNDI_MODEL_OUTBOUND)) {
4769  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",
4770  ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
4771  } else {
4772  if (ast_eid_cmp(&peer->eid, &empty_eid)) {
4773  /* Schedule any items for explicitly configured peers. */
4774  if (needregister) {
4775  peer->registerid = ast_sched_add(sched, 2000, do_register, peer);
4776  }
4777  qualify_peer(peer, 1);
4778  }
4779  }
4781 }
#define ast_free(a)
Definition: astmm.h:180
#define DEFAULT_MAXMS
Definition: chan_iax2.c:387
#define DUNDI_PORT
Definition: dundi.h:30
int ast_sockaddr_resolve(struct ast_sockaddr **addrs, const char *str, int flags, int family)
Parses a string with an IPv4 or IPv6 address and place results into an array.
Definition: netsock2.c:280
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:532
#define DUNDI_MODEL_SYMMETRIC
Definition: pbx_dundi.c:161
static dundi_eid empty_eid
Definition: pbx_dundi.c:212
#define DUNDI_MODEL_INBOUND
Definition: pbx_dundi.c:159
static void populate_addr(struct dundi_peer *peer, dundi_eid *eid)
Definition: pbx_dundi.c:4588
static void append_permission(struct permissionlist *permlist, const char *s, int allow)
Definition: pbx_dundi.c:4442
static void destroy_permissions(struct permissionlist *permlist)
Definition: pbx_dundi.c:4374
static void qualify_peer(struct dundi_peer *peer, int schedonly)
Definition: pbx_dundi.c:4565
#define DUNDI_MODEL_OUTBOUND
Definition: pbx_dundi.c:160
static int do_register(const void *data)
Definition: pbx_dundi.c:4531
static dundi_eid global_eid
Definition: pbx_dundi.c:198
int ast_sched_add(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
Adds a scheduled event.
Definition: sched.c:567
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: main/utils.c:2097
Socket address structure.
Definition: netsock2.h:97
struct ast_variable * next
char outkey[80]
Definition: pbx_dundi.c:310
struct dundi_peer::@445 list
unsigned int dynamic
Definition: pbx_dundi.c:334
struct dundi_peer::permissionlist permit
int qualifyid
Definition: pbx_dundi.c:313
int registerid
Definition: pbx_dundi.c:312
int pcmodel
Definition: pbx_dundi.c:332
struct permissionlist include
Definition: pbx_dundi.c:307
int registerexpire
Definition: pbx_dundi.c:325
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
Definition: main/utils.c:2990
int ast_str_to_eid(struct ast_eid *eid, const char *s)
Convert a string into an EID.
Definition: main/utils.c:2973

References dundi_peer::addr, append_permission(), ast_calloc, ast_copy_string(), ast_eid_cmp(), ast_eid_to_str(), ast_free, AST_LIST_EMPTY, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log, ast_sched_add(), AST_SCHED_DEL, ast_sockaddr_copy(), ast_sockaddr_isnull(), ast_sockaddr_resolve(), ast_sockaddr_set_port, ast_str_to_eid(), ast_true(), dundi_peer::dead, DEFAULT_MAXMS, destroy_permissions(), do_register(), DUNDI_MODEL_INBOUND, DUNDI_MODEL_OUTBOUND, DUNDI_MODEL_SYMMETRIC, DUNDI_PORT, dundi_peer::dynamic, dundi_peer::eid, empty_eid, global_eid, dundi_peer::include, dundi_peer::inkey, ast_variable::lineno, dundi_peer::list, LOG_WARNING, dundi_peer::maxms, dundi_peer::model, ast_variable::name, ast_variable::next, dundi_peer::order, dundi_peer::outkey, PARSE_PORT_FORBID, dundi_peer::pcmodel, dundi_peer::permit, populate_addr(), qualify_peer(), dundi_peer::qualifyid, dundi_peer::registerexpire, dundi_peer::registerid, dundi_peer::us_eid, and ast_variable::value.

Referenced by set_config().

◆ build_secret()

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

Definition at line 2110 of file pbx_dundi.c.

2111 {
2112  unsigned char tmp[16];
2113  char *s;
2114  build_iv(tmp);
2115  secret[0] = '\0';
2116  ast_base64encode(secret, tmp, sizeof(tmp), seclen);
2117  /* Eliminate potential bad characters */
2118  while((s = strchr(secret, ';'))) *s = '+';
2119  while((s = strchr(secret, '/'))) *s = '+';
2120  while((s = strchr(secret, ':'))) *s = '+';
2121  while((s = strchr(secret, '@'))) *s = '+';
2122 }
static int tmp()
Definition: bt_open.c:389
static void build_iv(unsigned char *iv)
Definition: pbx_dundi.c:533
int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
Encode data in base64.
Definition: main/utils.c:406

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

Referenced by check_password(), and load_password().

◆ build_transactions()

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

3701 {
3702  struct dundi_peer *p;
3703  int x;
3704  int res;
3705  int pass;
3706  int allowconnect;
3707  char eid_str[20];
3708  AST_LIST_LOCK(&peers);
3709  AST_LIST_TRAVERSE(&peers, p, list) {
3710  if (modeselect == 1) {
3711  /* Send the precache to push upstreams only! */
3712  pass = has_permission(&p->permit, dr->dcontext) && (p->pcmodel & DUNDI_MODEL_OUTBOUND);
3713  allowconnect = 1;
3714  } else {
3715  /* Normal lookup / EID query */
3716  pass = has_permission(&p->include, dr->dcontext);
3717  allowconnect = p->model & DUNDI_MODEL_OUTBOUND;
3718  }
3719  if (skip) {
3720  if (!ast_eid_cmp(skip, &p->eid))
3721  pass = 0;
3722  }
3723  if (pass) {
3724  if (p->order <= order) {
3725  /* Check order first, then check cache, regardless of
3726  omissions, this gets us more likely to not have an
3727  affected answer. */
3728  if((nocache || !(res = cache_lookup(dr, &p->eid, dr->crc32, &dr->expiration)))) {
3729  res = 0;
3730  /* Make sure we haven't already seen it and that it won't
3731  affect our answer */
3732  for (x=0;avoid[x];x++) {
3733  if (!ast_eid_cmp(avoid[x], &p->eid) || !ast_eid_cmp(avoid[x], &p->us_eid)) {
3734  /* If not a direct connection, it affects our answer */
3735  if (directs && !directs[x])
3737  break;
3738  }
3739  }
3740  /* Make sure we can ask */
3741  if (allowconnect) {
3742  if (!avoid[x] && (!blockempty || !dundi_eid_zero(&p->us_eid))) {
3743  /* Check for a matching or 0 cache entry */
3744  append_transaction(dr, p, ttl, avoid);
3745  } else {
3746  ast_debug(1, "Avoiding '%s' in transaction\n", ast_eid_to_str(eid_str, sizeof(eid_str), avoid[x]));
3747  }
3748  }
3749  }
3750  *foundcache |= res;
3751  } else if (!*skipped || (p->order < *skipped))
3752  *skipped = p->order;
3753  }
3754  }
3756 }
integer order
Definition: analys.c:66
int dundi_eid_zero(dundi_eid *eid)
Definition: dundi-parser.c:82
@ DUNDI_HINT_UNAFFECTED
Definition: dundi.h:94
static int cache_lookup(struct dundi_request *req, dundi_eid *peer_eid, uint32_t crc, int *lowexpiration)
Definition: pbx_dundi.c:1242
static int append_transaction(struct dundi_request *dr, struct dundi_peer *p, int ttl, dundi_eid *avoid[])
Definition: pbx_dundi.c:3642
static int has_permission(struct permissionlist *permlist, char *cont)
Definition: pbx_dundi.c:367
static char pass[512]
#define ast_clear_flag_nonstd(p, flag)
Definition: utils.h:180

References append_transaction(), ast_clear_flag_nonstd, ast_debug, ast_eid_cmp(), ast_eid_to_str(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, cache_lookup(), dr, dundi_eid_zero(), DUNDI_HINT_UNAFFECTED, DUNDI_MODEL_OUTBOUND, dundi_peer::eid, has_permission(), dundi_peer::include, dundi_peer::list, dundi_peer::model, order, dundi_peer::order, pass, dundi_peer::pcmodel, dundi_peer::permit, and dundi_peer::us_eid.

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

◆ cache_lookup()

static int cache_lookup ( struct dundi_request req,
dundi_eid peer_eid,
uint32_t  crc,
int *  lowexpiration 
)
static

Definition at line 1242 of file pbx_dundi.c.

1243 {
1244  char eid_str[20];
1245  char eidroot_str[20];
1246  time_t now;
1247  int res=0;
1248  int res2=0;
1249  char eid_str_full[20];
1250  char tmp[256]="";
1251  /* Enough space for largest value that can be stored in key. */
1252  char key[sizeof(eid_str) + sizeof(tmp) + sizeof(req->dcontext) + sizeof(eidroot_str) + sizeof("hint////r")];
1253  int x;
1254 
1255  time(&now);
1256  dundi_eid_to_str_short(eid_str, sizeof(eid_str), peer_eid);
1257  dundi_eid_to_str_short(eidroot_str, sizeof(eidroot_str), &req->root_eid);
1258  ast_eid_to_str(eid_str_full, sizeof(eid_str_full), peer_eid);
1259  snprintf(key, sizeof(key), "%s/%s/%s/e%08x", eid_str, req->number, req->dcontext, crc);
1260  res |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration);
1261  snprintf(key, sizeof(key), "%s/%s/%s/e%08x", eid_str, req->number, req->dcontext, (unsigned)0);
1262  res |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration);
1263  snprintf(key, sizeof(key), "%s/%s/%s/r%s", eid_str, req->number, req->dcontext, eidroot_str);
1264  res |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration);
1265  x = 0;
1266  if (!req->respcount) {
1267  while(!res2) {
1268  /* Look and see if we have a hint that would preclude us from looking at this
1269  peer for this number. */
1270  if (!(tmp[x] = req->number[x]))
1271  break;
1272  x++;
1273  /* Check for hints */
1274  snprintf(key, sizeof(key), "hint/%s/%s/%s/e%08x", eid_str, tmp, req->dcontext, crc);
1275  res2 |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration);
1276  snprintf(key, sizeof(key), "hint/%s/%s/%s/e%08x", eid_str, tmp, req->dcontext, (unsigned)0);
1277  res2 |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration);
1278  snprintf(key, sizeof(key), "hint/%s/%s/%s/r%s", eid_str, tmp, req->dcontext, eidroot_str);
1279  res2 |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration);
1280  if (res2) {
1281  if (strlen(tmp) > strlen(req->hmd->exten)) {
1282  /* Update meta data if appropriate */
1283  ast_copy_string(req->hmd->exten, tmp, sizeof(req->hmd->exten));
1284  }
1285  }
1286  }
1287  res |= res2;
1288  }
1289 
1290  return res;
1291 }
char * dundi_eid_to_str_short(char *s, int maxlen, dundi_eid *eid)
Definition: dundi-parser.c:54
static int cache_lookup_internal(time_t now, struct dundi_request *req, char *key, char *eid_str_full, int *lowexpiration)
Definition: pbx_dundi.c:1170
char exten[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:233
struct dundi_hint_metadata * hmd
Definition: pbx_dundi.c:280
char number[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:275
dundi_eid root_eid
Definition: pbx_dundi.c:277
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:274

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

Referenced by build_transactions().

◆ cache_lookup_internal()

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

Definition at line 1170 of file pbx_dundi.c.

1171 {
1172  char data[1024];
1173  char *ptr, *term, *src;
1174  int tech;
1175  struct ast_flags flags;
1176  int weight;
1177  int length;
1178  int z;
1179  char fs[256];
1180 
1181  /* Build request string */
1182  if (!ast_db_get("dundi/cache", key, data, sizeof(data))) {
1183  time_t timeout;
1184  ptr = data;
1185  if (!ast_get_time_t(ptr, &timeout, 0, &length)) {
1186  int expiration = timeout - now;
1187  if (expiration > 0) {
1188  ast_debug(1, "Found cache expiring in %d seconds!\n", expiration);
1189  ptr += length + 1;
1190  while((sscanf(ptr, "%30d/%30d/%30d/%n", (int *)&(flags.flags), &weight, &tech, &length) == 3)) {
1191  ptr += length;
1192  term = strchr(ptr, '|');
1193  if (term) {
1194  *term = '\0';
1195  src = strrchr(ptr, '/');
1196  if (src) {
1197  *src = '\0';
1198  src++;
1199  } else
1200  src = "";
1201  ast_debug(1, "Found cached answer '%s/%s' originally from '%s' with flags '%s' on behalf of '%s'\n",
1202  tech2str(tech), ptr, src, dundi_flags2str(fs, sizeof(fs), flags.flags), eid_str_full);
1203  /* Make sure it's not already there */
1204  for (z=0;z<req->respcount;z++) {
1205  if ((req->dr[z].techint == tech) &&
1206  !strcmp(req->dr[z].dest, ptr))
1207  break;
1208  }
1209  if (z == req->respcount) {
1210  /* Copy into parent responses */
1211  ast_copy_flags(&(req->dr[req->respcount]), &flags, AST_FLAGS_ALL);
1212  req->dr[req->respcount].weight = weight;
1213  req->dr[req->respcount].techint = tech;
1214  req->dr[req->respcount].expiration = expiration;
1215  dundi_str_short_to_eid(&req->dr[req->respcount].eid, src);
1216  ast_eid_to_str(req->dr[req->respcount].eid_str,
1217  sizeof(req->dr[req->respcount].eid_str), &req->dr[req->respcount].eid);
1218  ast_copy_string(req->dr[req->respcount].dest, ptr,
1219  sizeof(req->dr[req->respcount].dest));
1220  ast_copy_string(req->dr[req->respcount].tech, tech2str(tech),
1221  sizeof(req->dr[req->respcount].tech));
1222  req->respcount++;
1224  } else if (req->dr[z].weight > weight)
1225  req->dr[z].weight = weight;
1226  ptr = term + 1;
1227  }
1228  }
1229  /* We found *something* cached */
1230  if (expiration < *lowexpiration)
1231  *lowexpiration = expiration;
1232  return 1;
1233  } else
1234  ast_db_del("dundi/cache", key);
1235  } else
1236  ast_db_del("dundi/cache", key);
1237  }
1238 
1239  return 0;
1240 }
char weight
int ast_db_get(const char *family, const char *key, char *value, int valuelen)
Get key value specified by family/key.
Definition: main/db.c:412
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: main/db.c:429
int dundi_str_short_to_eid(dundi_eid *eid, const char *s)
Definition: dundi-parser.c:70
char * dundi_flags2str(char *buf, int bufsiz, int flags)
Definition: dundi-parser.c:246
@ DUNDI_HINT_DONT_ASK
Definition: dundi.h:92
static char * tech2str(int tech)
Definition: pbx_dundi.c:380
int ast_get_time_t(const char *src, time_t *dst, time_t _default, int *consumed)
Parse a time (integer) string.
Definition: main/utils.c:2344
Structure used to handle boolean flags.
Definition: utils.h:199
unsigned int flags
Definition: utils.h:200
struct dundi_result * dr
Definition: pbx_dundi.c:278
char dest[256]
Definition: dundi.h:233
char eid_str[20]
Definition: dundi.h:231
int techint
Definition: dundi.h:229
char tech[10]
Definition: dundi.h:232
int weight
Definition: dundi.h:227
int expiration
Definition: dundi.h:228
dundi_eid eid
Definition: dundi.h:230
#define ast_copy_flags(dest, src, flagz)
Definition: utils.h:84
#define AST_FLAGS_ALL
Definition: utils.h:196

References ast_clear_flag_nonstd, ast_copy_flags, ast_copy_string(), ast_db_del(), ast_db_get(), ast_debug, ast_eid_to_str(), AST_FLAGS_ALL, ast_get_time_t(), dundi_result::dest, dundi_request::dr, 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, dundi_request::respcount, dundi_result::tech, dundi_mapping::tech, tech2str(), dundi_result::techint, weight, and dundi_result::weight.

Referenced by cache_lookup().

◆ cache_save()

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

Definition at line 899 of file pbx_dundi.c.

900 {
901  int x;
902  char key1[256];
903  char key2[256];
904  char data[1024];
905  char eidpeer_str[20];
906  char eidroot_str[20];
907  time_t timeout;
908 
909  if (expiration < 1)
910  expiration = dundi_cache_time;
911 
912  /* Keep pushes a little longer, cut pulls a little short */
913  if (push)
914  expiration += 10;
915  else
916  expiration -= 10;
917  if (expiration < 1)
918  expiration = 1;
919  dundi_eid_to_str_short(eidpeer_str, sizeof(eidpeer_str), eidpeer);
920  dundi_eid_to_str_short(eidroot_str, sizeof(eidroot_str), &req->root_eid);
921  snprintf(key1, sizeof(key1), "%s/%s/%s/e%08x", eidpeer_str, req->number, req->dcontext, unaffected ? 0 : req->crc32);
922  snprintf(key2, sizeof(key2), "%s/%s/%s/r%s", eidpeer_str, req->number, req->dcontext, eidroot_str);
923  /* Build request string */
924  time(&timeout);
925  timeout += expiration;
926  snprintf(data, sizeof(data), "%ld|", (long)(timeout));
927  for (x=start;x<req->respcount;x++) {
928  /* Skip anything with an illegal pipe in it */
929  if (strchr(req->dr[x].dest, '|'))
930  continue;
931  snprintf(data + strlen(data), sizeof(data) - strlen(data), "%u/%d/%d/%s/%s|",
932  req->dr[x].flags, req->dr[x].weight, req->dr[x].techint, req->dr[x].dest,
933  dundi_eid_to_str_short(eidpeer_str, sizeof(eidpeer_str), &req->dr[x].eid));
934  }
935  ast_db_put("dundi/cache", key1, data);
936  ast_db_put("dundi/cache", key2, data);
937  return 0;
938 }
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: main/db.c:327
static int dundi_cache_time
Definition: pbx_dundi.c:196
uint32_t crc32
Definition: pbx_dundi.c:286
unsigned int flags
Definition: dundi.h:226

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

Referenced by dundi_prop_precache(), and handle_command_response().

◆ cache_save_hint()

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

Definition at line 864 of file pbx_dundi.c.

865 {
866  int unaffected;
867  char key1[256];
868  char key2[256];
869  char eidpeer_str[20];
870  char eidroot_str[20];
871  char data[80];
872  time_t timeout;
873 
874  if (expiration < 0)
875  expiration = dundi_cache_time;
876 
877  /* Only cache hint if "don't ask" is there... */
878  if (!ast_test_flag_nonstd(hint, htons(DUNDI_HINT_DONT_ASK)))
879  return 0;
880 
881  unaffected = ast_test_flag_nonstd(hint, htons(DUNDI_HINT_UNAFFECTED));
882 
883  dundi_eid_to_str_short(eidpeer_str, sizeof(eidpeer_str), eidpeer);
884  dundi_eid_to_str_short(eidroot_str, sizeof(eidroot_str), &req->root_eid);
885  snprintf(key1, sizeof(key1), "hint/%s/%s/%s/e%08x", eidpeer_str, hint->data, req->dcontext, unaffected ? 0 : req->crc32);
886  snprintf(key2, sizeof(key2), "hint/%s/%s/%s/r%s", eidpeer_str, hint->data, req->dcontext, eidroot_str);
887 
888  time(&timeout);
889  timeout += expiration;
890  snprintf(data, sizeof(data), "%ld|", (long)(timeout));
891 
892  ast_db_put("dundi/cache", key1, data);
893  ast_debug(1, "Caching hint at '%s'\n", key1);
894  ast_db_put("dundi/cache", key2, data);
895  ast_debug(1, "Caching hint at '%s'\n", key2);
896  return 0;
897 }
unsigned char data[0]
Definition: dundi.h:112
#define ast_test_flag_nonstd(p, flag)
Definition: utils.h:173

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

Referenced by dundi_prop_precache(), and handle_command_response().

◆ cancel_request()

static void cancel_request ( struct dundi_request dr)
static

Definition at line 3674 of file pbx_dundi.c.

3675 {
3676  struct dundi_transaction *trans;
3677 
3678  AST_LIST_LOCK(&peers);
3679  while ((trans = AST_LIST_REMOVE_HEAD(&dr->trans, parentlist))) {
3680  /* Orphan transaction from request */
3681  trans->parent = NULL;
3682  /* Send final cancel */
3683  dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
3684  }
3686 }
#define DUNDI_COMMAND_CANCEL
Definition: dundi.h:171
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
static int dundi_send(struct dundi_transaction *trans, int cmdresp, int flags, int final, struct dundi_ie_data *ied)
Definition: pbx_dundi.c:3308
#define NULL
Definition: resample.c:96

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

Referenced by dundi_lookup_internal(), and dundi_precache_internal().

◆ check_key()

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

Definition at line 1492 of file pbx_dundi.c.

1493 {
1494  unsigned char dst[128];
1495  int res;
1496  struct ast_key *key, *skey;
1497  char eid_str[20];
1498  ast_debug(1, "Expected '%08x' got '%08x'\n", peer->them_keycrc32, keycrc32);
1499  if (peer->them_keycrc32 && (peer->them_keycrc32 == keycrc32)) {
1500  /* A match */
1501  return 1;
1502  } else if (!newkey || !newsig)
1503  return 0;
1504  if (!memcmp(peer->rxenckey, newkey, 128) &&
1505  !memcmp(peer->rxenckey + 128, newsig, 128)) {
1506  /* By definition, a match */
1507  return 1;
1508  }
1509  /* Decrypt key */
1510  key = ast_key_get(peer->outkey, AST_KEY_PRIVATE);
1511  if (!key) {
1512  ast_log(LOG_NOTICE, "Unable to find key '%s' to decode shared key from '%s'\n",
1513  peer->outkey, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
1514  return -1;
1515  }
1516 
1517  skey = ast_key_get(peer->inkey, AST_KEY_PUBLIC);
1518  if (!skey) {
1519  ast_log(LOG_NOTICE, "Unable to find key '%s' to verify shared key from '%s'\n",
1520  peer->inkey, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
1521  return -1;
1522  }
1523 
1524  /* First check signature */
1525  res = ast_check_signature_bin(skey, (char *)newkey, 128, newsig);
1526  if (res)
1527  return 0;
1528 
1529  res = ast_decrypt_bin(dst, newkey, sizeof(dst), key);
1530  if (res != 16) {
1531  if (res >= 0)
1532  ast_log(LOG_NOTICE, "Weird, key decoded to the wrong size (%d)\n", res);
1533  return 0;
1534  }
1535  /* Decrypted, passes signature */
1536  ast_debug(1, "Wow, new key combo passed signature and decrypt!\n");
1537  memcpy(peer->rxenckey, newkey, 128);
1538  memcpy(peer->rxenckey + 128, newsig, 128);
1539  peer->them_keycrc32 = crc32(0L, peer->rxenckey, 128);
1540  ast_aes_set_decrypt_key(dst, &peer->them_dcx);
1541  ast_aes_set_encrypt_key(dst, &peer->them_ecx);
1542  return 1;
1543 }
struct ast_key * ast_key_get(const char *kname, int ktype)
Retrieve a key.
Definition: res_crypto.c:143
int ast_aes_set_encrypt_key(const unsigned char *key, ast_aes_encrypt_key *ctx)
Set an encryption key.
Definition: res_crypto.c:468
#define AST_KEY_PUBLIC
Definition: crypto.h:42
int ast_check_signature_bin(struct ast_key *key, const char *msg, int msglen, const unsigned char *dsig)
Check the authenticity of a message signature using a given public key.
Definition: res_crypto.c:418
#define AST_KEY_PRIVATE
Definition: crypto.h:43
int ast_aes_set_decrypt_key(const unsigned char *key, ast_aes_decrypt_key *ctx)
Set a decryption key.
Definition: res_crypto.c:473
int ast_decrypt_bin(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key)
Decrypt a message using a given private key.
Definition: res_crypto.c:338
#define LOG_NOTICE
uint32_t them_keycrc32
Definition: pbx_dundi.c:321
unsigned char rxenckey[256]
Definition: pbx_dundi.c:317
ast_aes_decrypt_key them_dcx
Definition: pbx_dundi.c:323
ast_aes_encrypt_key them_ecx
Definition: pbx_dundi.c:322

References ast_aes_set_decrypt_key(), ast_aes_set_encrypt_key(), ast_check_signature_bin(), ast_debug, ast_decrypt_bin(), ast_eid_to_str(), ast_key_get(), AST_KEY_PRIVATE, AST_KEY_PUBLIC, ast_log, dundi_peer::eid, dundi_peer::inkey, LOG_NOTICE, dundi_peer::outkey, dundi_peer::rxenckey, dundi_peer::them_dcx, dundi_peer::them_ecx, and dundi_peer::them_keycrc32.

Referenced by handle_command_response().

◆ check_password()

static void check_password ( void  )
static

Definition at line 2177 of file pbx_dundi.c.

2178 {
2179  char oldsecret[80];
2180  time_t now;
2181 
2182  time(&now);
2183 #if 0
2184  printf("%ld/%ld\n", now, rotatetime);
2185 #endif
2186  if ((now - rotatetime) >= 0) {
2187  /* Time to rotate keys */
2188  ast_copy_string(oldsecret, cursecret, sizeof(oldsecret));
2189  build_secret(cursecret, sizeof(cursecret));
2190  save_secret(cursecret, oldsecret);
2191  }
2192 }
static void build_secret(char *secret, int seclen)
Definition: pbx_dundi.c:2110
static void save_secret(const char *newkey, const char *oldkey)
Definition: pbx_dundi.c:2125
static char cursecret[80]
Definition: pbx_dundi.c:209
static time_t rotatetime
Definition: pbx_dundi.c:211

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

Referenced by network_thread().

◆ check_request()

static int check_request ( struct dundi_request dr)
static

Definition at line 3795 of file pbx_dundi.c.

3796 {
3797  struct dundi_request *cur;
3798 
3799  AST_LIST_LOCK(&peers);
3800  AST_LIST_TRAVERSE(&requests, cur, list) {
3801  if (cur == dr)
3802  break;
3803  }
3805 
3806  return cur ? 1 : 0;
3807 }
struct dundi_request::@443 list

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

Referenced by dundi_lookup_internal().

◆ complete_peer_helper()

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

Definition at line 2417 of file pbx_dundi.c.

2418 {
2419  int which=0, len;
2420  char *ret = NULL;
2421  struct dundi_peer *p;
2422  char eid_str[20];
2423 
2424  if (pos != rpos)
2425  return NULL;
2426  AST_LIST_LOCK(&peers);
2427  len = strlen(word);
2428  AST_LIST_TRAVERSE(&peers, p, list) {
2429  const char *s = ast_eid_to_str(eid_str, sizeof(eid_str), &p->eid);
2430  if (!strncasecmp(word, s, len) && ++which > state) {
2431  ret = ast_strdup(s);
2432  break;
2433  }
2434  }
2436  return ret;
2437 }
short word
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)

References ast_eid_to_str(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strdup, dundi_peer::eid, len(), dundi_peer::list, and NULL.

Referenced by dundi_show_peer().

◆ create_transaction()

static struct dundi_transaction * create_transaction ( struct dundi_peer p)
static

Definition at line 3137 of file pbx_dundi.c.

3138 {
3139  struct dundi_transaction *trans;
3140  int tid;
3141 
3142  /* Don't allow creation of transactions to non-registered peers */
3143  if (p && ast_sockaddr_isnull(&p->addr)) {
3144  return NULL;
3145  }
3146  tid = get_trans_id();
3147  if (tid < 1)
3148  return NULL;
3149  if (!(trans = ast_calloc(1, sizeof(*trans))))
3150  return NULL;
3151 
3152  if (global_storehistory) {
3153  trans->start = ast_tvnow();
3154  ast_set_flag(trans, FLAG_STOREHIST);
3155  }
3157  trans->autokillid = -1;
3158  if (p) {
3159  apply_peer(trans, p);
3160  if (!p->sentfullkey)
3162  }
3163  trans->strans = tid;
3164  AST_LIST_INSERT_HEAD(&alltrans, trans, all);
3165 
3166  return trans;
3167 }
static void apply_peer(struct dundi_transaction *trans, struct dundi_peer *p)
Definition: pbx_dundi.c:1295
static int get_trans_id(void)
Definition: pbx_dundi.c:480
static int global_storehistory
Definition: pbx_dundi.c:200
int sentfullkey
Definition: pbx_dundi.c:314
struct dundi_transaction::@441 all
unsigned short strans
Definition: pbx_dundi.c:260
struct timeval start
Definition: pbx_dundi.c:247
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:157

References dundi_peer::addr, dundi_transaction::all, apply_peer(), ast_calloc, AST_LIST_INSERT_HEAD, ast_set_flag, ast_sockaddr_isnull(), ast_tvnow(), dundi_transaction::autokillid, DUNDI_DEFAULT_RETRANS_TIMER, FLAG_SENDFULLKEY, FLAG_STOREHIST, get_trans_id(), global_storehistory, NULL, dundi_transaction::retranstimer, dundi_peer::sentfullkey, dundi_transaction::start, and dundi_transaction::strans.

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

◆ decrypt_memcpy()

static int decrypt_memcpy ( unsigned char *  dst,
unsigned char *  src,
int  len,
unsigned char *  iv,
ast_aes_decrypt_key dcx 
)
static

Definition at line 1389 of file pbx_dundi.c.

1390 {
1391  unsigned char lastblock[16];
1392  int x;
1393  memcpy(lastblock, iv, sizeof(lastblock));
1394  while(len > 0) {
1395  ast_aes_decrypt(src, dst, dcx);
1396  for (x=0;x<16;x++)
1397  dst[x] ^= lastblock[x];
1398  memcpy(lastblock, src, sizeof(lastblock));
1399  dst += 16;
1400  src += 16;
1401  len -= 16;
1402  }
1403  return 0;
1404 }
void ast_aes_decrypt(const unsigned char *in, unsigned char *out, const ast_aes_decrypt_key *ctx)
AES decrypt data.
Definition: res_crypto.c:483

References ast_aes_decrypt(), and len().

Referenced by dundi_decrypt().

◆ deep_copy_peer()

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

Definition at line 1545 of file pbx_dundi.c.

1546 {
1547  struct permission *cur, *perm;
1548 
1549  *peer_dst = *peer_src;
1550  AST_LIST_NEXT(peer_dst, list) = NULL;
1551 
1552  /* Scheduled items cannot go with the copy */
1553  peer_dst->registerid = -1;
1554  peer_dst->qualifyid = -1;
1555  peer_dst->registerexpire = -1;
1556 
1557  /* Transactions and lookup history cannot go with the copy either */
1558  peer_dst->regtrans = NULL;
1559  peer_dst->qualtrans = NULL;
1560  memset(&peer_dst->lookups, 0, sizeof(peer_dst->lookups));
1561 
1562  memset(&peer_dst->permit, 0, sizeof(peer_dst->permit));
1563  memset(&peer_dst->include, 0, sizeof(peer_dst->permit));
1564 
1565  AST_LIST_TRAVERSE(&peer_src->permit, cur, list) {
1566  if (!(perm = ast_calloc(1, sizeof(*perm) + strlen(cur->name) + 1)))
1567  continue;
1568 
1569  perm->allow = cur->allow;
1570  strcpy(perm->name, cur->name);
1571 
1572  AST_LIST_INSERT_HEAD(&peer_dst->permit, perm, list);
1573  }
1574 
1575  AST_LIST_TRAVERSE(&peer_src->include, cur, list) {
1576  if (!(perm = ast_calloc(1, sizeof(*perm) + strlen(cur->name) + 1)))
1577  continue;
1578 
1579  perm->allow = cur->allow;
1580  strcpy(perm->name, cur->name);
1581 
1582  AST_LIST_INSERT_HEAD(&peer_dst->include, perm, list);
1583  }
1584 }
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:439
char * lookups[DUNDI_TIMING_HISTORY]
Definition: pbx_dundi.c:327
struct dundi_transaction * regtrans
Definition: pbx_dundi.c:329
struct dundi_transaction * qualtrans
Definition: pbx_dundi.c:330

References permission::allow, ast_calloc, AST_LIST_INSERT_HEAD, AST_LIST_NEXT, AST_LIST_TRAVERSE, dundi_peer::include, permission::list, dundi_peer::lookups, permission::name, NULL, dundi_peer::permit, dundi_peer::qualifyid, dundi_peer::qualtrans, dundi_peer::registerexpire, dundi_peer::registerid, and dundi_peer::regtrans.

Referenced by handle_command_response().

◆ destroy_map()

static void destroy_map ( struct dundi_mapping map)
static

Definition at line 4406 of file pbx_dundi.c.

4407 {
4408  ast_free(map->weightstr);
4409  ast_free(map);
4410 }

References ast_free, and dundi_mapping::weightstr.

Referenced by prune_mappings().

◆ destroy_packet()

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

Definition at line 3194 of file pbx_dundi.c.

3195 {
3196  if (pack->parent)
3197  AST_LIST_REMOVE(&pack->parent->packets, pack, list);
3198  AST_SCHED_DEL(sched, pack->retransid);
3199  if (needfree)
3200  ast_free(pack);
3201 }
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Definition: linkedlists.h:856
struct dundi_transaction * parent
Definition: pbx_dundi.c:225

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

Referenced by ack_trans().

◆ destroy_packets()

static void destroy_packets ( struct packetlist *  p)
static

Definition at line 2010 of file pbx_dundi.c.

2011 {
2012  struct dundi_packet *pack;
2013 
2014  while ((pack = AST_LIST_REMOVE_HEAD(p, list))) {
2015  AST_SCHED_DEL(sched, pack->retransid);
2016  ast_free(pack);
2017  }
2018 }

References ast_free, AST_LIST_REMOVE_HEAD, AST_SCHED_DEL, dundi_packet::list, and dundi_packet::retransid.

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

◆ destroy_peer()

static void destroy_peer ( struct dundi_peer peer)
static

Definition at line 4382 of file pbx_dundi.c.

4383 {
4384  int idx;
4385 
4387  AST_SCHED_DEL(sched, peer->registerid);
4388  if (peer->regtrans) {
4389  destroy_trans(peer->regtrans, 0);
4390  }
4391  AST_SCHED_DEL(sched, peer->qualifyid);
4392  if (peer->qualtrans) {
4393  destroy_trans(peer->qualtrans, 0);
4394  }
4395  destroy_permissions(&peer->permit);
4396  destroy_permissions(&peer->include);
4397 
4398  /* Release lookup history */
4399  for (idx = 0; idx < ARRAY_LEN(peer->lookups); ++idx) {
4400  ast_free(peer->lookups[idx]);
4401  }
4402 
4403  ast_free(peer);
4404 }
#define ARRAY_LEN(a)
Definition: utils.h:661

References ARRAY_LEN, ast_free, AST_SCHED_DEL, destroy_permissions(), destroy_trans(), dundi_peer::include, dundi_peer::lookups, dundi_peer::permit, dundi_peer::qualifyid, dundi_peer::qualtrans, dundi_peer::registerexpire, dundi_peer::registerid, and dundi_peer::regtrans.

Referenced by prune_peers().

◆ destroy_permissions()

static void destroy_permissions ( struct permissionlist *  permlist)
static

Definition at line 4374 of file pbx_dundi.c.

4375 {
4376  struct permission *perm;
4377 
4378  while ((perm = AST_LIST_REMOVE_HEAD(permlist, list)))
4379  ast_free(perm);
4380 }

References ast_free, AST_LIST_REMOVE_HEAD, and permission::list.

Referenced by build_peer(), and destroy_peer().

◆ destroy_trans()

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

Definition at line 3203 of file pbx_dundi.c.

3204 {
3205  struct dundi_peer *peer;
3206  int ms;
3207  int x;
3208  int cnt;
3209  char eid_str[20];
3211  AST_LIST_TRAVERSE(&peers, peer, list) {
3212  if (peer->regtrans == trans)
3213  peer->regtrans = NULL;
3214  if (peer->qualtrans == trans) {
3215  if (fromtimeout) {
3216  if (peer->lastms > -1)
3217  ast_log(LOG_NOTICE, "Peer '%s' has become UNREACHABLE!\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
3218  peer->lastms = -1;
3219  } else {
3220  ms = ast_tvdiff_ms(ast_tvnow(), peer->qualtx);
3221  if (ms < 1)
3222  ms = 1;
3223  if (ms < peer->maxms) {
3224  if ((peer->lastms >= peer->maxms) || (peer->lastms < 0))
3225  ast_log(LOG_NOTICE, "Peer '%s' has become REACHABLE!\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
3226  } else if (peer->lastms < peer->maxms) {
3227  ast_log(LOG_NOTICE, "Peer '%s' has become TOO LAGGED (%d ms)\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), ms);
3228  }
3229  peer->lastms = ms;
3230  }
3231  peer->qualtrans = NULL;
3232  }
3233  if (ast_test_flag(trans, FLAG_STOREHIST)) {
3234  if (trans->parent && !ast_strlen_zero(trans->parent->number)) {
3235  if (!ast_eid_cmp(&trans->them_eid, &peer->eid)) {
3236  peer->avgms = 0;
3237  cnt = 0;
3239  for (x=DUNDI_TIMING_HISTORY-1;x>0;x--) {
3240  peer->lookuptimes[x] = peer->lookuptimes[x-1];
3241  peer->lookups[x] = peer->lookups[x-1];
3242  if (peer->lookups[x]) {
3243  peer->avgms += peer->lookuptimes[x];
3244  cnt++;
3245  }
3246  }
3247  peer->lookuptimes[0] = ast_tvdiff_ms(ast_tvnow(), trans->start);
3248  peer->lookups[0] = ast_malloc(strlen(trans->parent->number) + strlen(trans->parent->dcontext) + 2);
3249  if (peer->lookups[0]) {
3250  sprintf(peer->lookups[0], "%s@%s", trans->parent->number, trans->parent->dcontext);
3251  peer->avgms += peer->lookuptimes[0];
3252  cnt++;
3253  }
3254  if (cnt)
3255  peer->avgms /= cnt;
3256  }
3257  }
3258  }
3259  }
3260  }
3261  if (trans->parent) {
3262  /* Unlink from parent if appropriate */
3263  AST_LIST_REMOVE(&trans->parent->trans, trans, parentlist);
3264  if (AST_LIST_EMPTY(&trans->parent->trans)) {
3265  /* Wake up sleeper */
3266  if (trans->parent->pfds[1] > -1) {
3267  if (write(trans->parent->pfds[1], "killa!", 6) < 0) {
3268  ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
3269  }
3270  }
3271  }
3272  }
3273  /* Unlink from all trans */
3274  AST_LIST_REMOVE(&alltrans, trans, all);
3275  destroy_packets(&trans->packets);
3276  destroy_packets(&trans->lasttrans);
3277  AST_SCHED_DEL(sched, trans->autokillid);
3278  if (trans->thread) {
3279  /* If used by a thread, mark as dead and be done */
3280  ast_set_flag(trans, FLAG_DEAD);
3281  } else
3282  ast_free(trans);
3283 }
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
int errno
#define DUNDI_TIMING_HISTORY
Definition: pbx_dundi.c:164
int lookuptimes[DUNDI_TIMING_HISTORY]
Definition: pbx_dundi.c:326
struct timeval qualtx
Definition: pbx_dundi.c:337
int pfds[2]
Definition: pbx_dundi.c:285
struct dundi_request::@442 trans
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:105
#define ast_test_flag(p, flag)
Definition: utils.h:63

References ast_eid_cmp(), ast_eid_to_str(), ast_free, AST_LIST_EMPTY, AST_LIST_REMOVE, AST_LIST_TRAVERSE, ast_log, ast_malloc, AST_SCHED_DEL, ast_set_flag, ast_strlen_zero(), ast_test_flag, ast_tvdiff_ms(), ast_tvnow(), dundi_transaction::autokillid, dundi_peer::avgms, dundi_request::dcontext, destroy_packets(), DUNDI_TIMING_HISTORY, dundi_peer::eid, errno, FLAG_DEAD, FLAG_ISQUAL, FLAG_ISREG, FLAG_STOREHIST, dundi_peer::lastms, dundi_transaction::lasttrans, dundi_peer::list, LOG_NOTICE, LOG_WARNING, dundi_peer::lookups, dundi_peer::lookuptimes, dundi_peer::maxms, NULL, dundi_request::number, dundi_transaction::packets, dundi_transaction::parent, 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().

◆ discover_transactions()

static int discover_transactions ( struct dundi_request dr)
static

Definition at line 3525 of file pbx_dundi.c.

3526 {
3527  struct dundi_transaction *trans;
3528  AST_LIST_LOCK(&peers);
3529  AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) {
3530  dundi_discover(trans);
3531  }
3533  return 0;
3534 }
static int dundi_discover(struct dundi_transaction *trans)
Definition: pbx_dundi.c:3413

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

Referenced by dundi_lookup_internal().

◆ do_autokill()

static int do_autokill ( const void *  data)
static

Definition at line 3380 of file pbx_dundi.c.

3381 {
3382  struct dundi_transaction *trans = (struct dundi_transaction *)data;
3383  char eid_str[20];
3384  ast_log(LOG_NOTICE, "Transaction to '%s' took too long to ACK, destroying\n",
3385  ast_eid_to_str(eid_str, sizeof(eid_str), &trans->them_eid));
3386  trans->autokillid = -1;
3387  destroy_trans(trans, 0); /* We could actually set it to 1 instead of 0, but we won't ;-) */
3388  return 0;
3389 }

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

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

◆ do_qualify()

static int do_qualify ( const void *  data)
static

Definition at line 4557 of file pbx_dundi.c.

4558 {
4559  struct dundi_peer *peer = (struct dundi_peer *)data;
4560  peer->qualifyid = -1;
4561  qualify_peer(peer, 0);
4562  return 0;
4563 }

References qualify_peer(), and dundi_peer::qualifyid.

Referenced by qualify_peer().

◆ do_register()

static int do_register ( const void *  data)
static
Note
Called with the peers list already locked

Definition at line 4531 of file pbx_dundi.c.

4532 {
4533  struct dundi_ie_data ied;
4534  struct dundi_peer *peer = (struct dundi_peer *)data;
4535  char eid_str[20];
4536  char eid_str2[20];
4537  ast_debug(1, "Register us as '%s' to '%s'\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->us_eid), ast_eid_to_str(eid_str2, sizeof(eid_str2), &peer->eid));
4539  /* Destroy old transaction if there is one */
4540  if (peer->regtrans)
4541  destroy_trans(peer->regtrans, 0);
4542  peer->regtrans = create_transaction(peer);
4543  if (peer->regtrans) {
4545  memset(&ied, 0, sizeof(ied));
4549  dundi_send(peer->regtrans, DUNDI_COMMAND_REGREQ, 0, 0, &ied);
4550 
4551  } else
4552  ast_log(LOG_NOTICE, "Unable to create new transaction for registering to '%s'!\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
4553 
4554  return 0;
4555 }
int dundi_ie_append_eid(struct dundi_ie_data *ied, unsigned char ie, dundi_eid *eid)
Definition: dundi-parser.c:610
int dundi_ie_append_short(struct dundi_ie_data *ied, unsigned char ie, unsigned short value)
Definition: dundi-parser.c:598
#define DUNDI_IE_VERSION
Definition: dundi.h:188
#define DUNDI_DEFAULT_VERSION
Definition: dundi.h:217
#define DUNDI_IE_EXPIRATION
Definition: dundi.h:189
#define DUNDI_IE_EID
Definition: dundi.h:182
#define DUNDI_COMMAND_REGREQ
Definition: dundi.h:169
static int default_expiration
Definition: pbx_dundi.c:199

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

Referenced by build_peer().

◆ do_register_expire()

static int do_register_expire ( const void *  data)
static
Note
Called with the peers list already locked

Definition at line 1321 of file pbx_dundi.c.

1322 {
1323  struct dundi_peer *peer = (struct dundi_peer *)data;
1324  char eid_str[20];
1325 
1326  ast_debug(1, "Register expired for '%s'\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
1327  ast_db_del("dundi/dpeers", dundi_eid_to_str_short(eid_str, sizeof(eid_str), &peer->eid));
1328  peer->registerexpire = -1;
1329  peer->lastms = 0;
1330  ast_sockaddr_setnull(&peer->addr);
1331  return 0;
1332 }
static void ast_sockaddr_setnull(struct ast_sockaddr *addr)
Sets address addr to null.
Definition: netsock2.h:138

References dundi_peer::addr, ast_db_del(), ast_debug, ast_eid_to_str(), ast_sockaddr_setnull(), dundi_eid_to_str_short(), dundi_peer::eid, dundi_peer::lastms, and dundi_peer::registerexpire.

Referenced by handle_command_response(), and populate_addr().

◆ drds_destroy()

static void drds_destroy ( struct dundi_result_datastore drds)
static

Definition at line 4199 of file pbx_dundi.c.

4200 {
4201  ast_free(drds);
4202 }

References ast_free.

Referenced by drds_destroy_cb().

◆ drds_destroy_cb()

static void drds_destroy_cb ( void *  data)
static

Definition at line 4204 of file pbx_dundi.c.

4205 {
4206  struct dundi_result_datastore *drds = data;
4207  drds_destroy(drds);
4208 }
static void drds_destroy(struct dundi_result_datastore *drds)
Definition: pbx_dundi.c:4199

References drds_destroy().

◆ dundi_ack()

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

Definition at line 451 of file pbx_dundi.c.

452 {
453  return dundi_send(trans, DUNDI_COMMAND_ACK, 0, final, NULL);
454 }
#define DUNDI_COMMAND_ACK
Definition: dundi.h:159

References DUNDI_COMMAND_ACK, dundi_send(), and NULL.

Referenced by handle_command_response(), and handle_frame().

◆ dundi_answer_entity()

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

Definition at line 809 of file pbx_dundi.c.

810 {
811  struct dundi_query_state *st;
812  int totallen;
813  int x;
814  int skipfirst=0;
815  char eid_str[20];
816  char *s;
817  pthread_t lookupthread;
818 
819  if (ies->eidcount > 1) {
820  /* Since it is a requirement that the first EID is the authenticating host
821  and the last EID is the root, it is permissible that the first and last EID
822  could be the same. In that case, we should go ahead copy only the "root" section
823  since we will not need it for authentication. */
824  if (!ast_eid_cmp(ies->eids[0], ies->eids[ies->eidcount - 1]))
825  skipfirst = 1;
826  }
827  totallen = sizeof(struct dundi_query_state);
828  totallen += (ies->eidcount - skipfirst) * sizeof(dundi_eid);
829  st = ast_calloc(1, totallen);
830  if (st) {
832  memcpy(&st->reqeid, ies->reqeid, sizeof(st->reqeid));
833  st->trans = trans;
834  st->ttl = ies->ttl - 1;
835  if (st->ttl < 0)
836  st->ttl = 0;
837  s = st->fluffy;
838  for (x=skipfirst;ies->eids[x];x++) {
839  st->eids[x-skipfirst] = (dundi_eid *)s;
840  *st->eids[x-skipfirst] = *ies->eids[x];
841  s += sizeof(dundi_eid);
842  }
843  ast_debug(1, "Answering EID query for '%s@%s'!\n", ast_eid_to_str(eid_str, sizeof(eid_str), ies->reqeid), ies->called_context);
844 
845  trans->thread = 1;
846  if (ast_pthread_create_detached(&lookupthread, NULL, dundi_query_thread, st)) {
847  struct dundi_ie_data ied = { 0, };
848  trans->thread = 0;
849  ast_log(LOG_WARNING, "Unable to create thread!\n");
850  ast_free(st);
851  dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of threads");
852  dundi_send(trans, DUNDI_COMMAND_EIDRESPONSE, 0, 1, &ied);
853  return -1;
854  }
855  } else {
856  struct dundi_ie_data ied = { 0, };
858  dundi_send(trans, DUNDI_COMMAND_EIDRESPONSE, 0, 1, &ied);
859  return -1;
860  }
861  return 0;
862 }
int dundi_ie_append_cause(struct dundi_ie_data *ied, unsigned char ie, unsigned char cause, char *data)
Definition: dundi-parser.c:499
struct ast_eid dundi_eid
Definition: dundi.h:32
#define DUNDI_IE_CAUSE
Definition: dundi.h:191
@ DUNDI_CAUSE_GENERAL
Definition: dundi.h:119
#define DUNDI_COMMAND_EIDRESPONSE
Definition: dundi.h:163
static void * dundi_query_thread(void *data)
Definition: pbx_dundi.c:754
dundi_eid * reqeid
Definition: dundi-parser.h:24
dundi_eid * eids[DUNDI_MAX_STACK+1]
Definition: dundi-parser.h:22
char * called_context
Definition: dundi-parser.h:26
int eidcount
Definition: dundi-parser.h:25
char called_context[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:547
dundi_eid * eids[DUNDI_MAX_STACK+1]
Definition: pbx_dundi.c:544
dundi_eid reqeid
Definition: pbx_dundi.c:546
struct dundi_transaction * trans
Definition: pbx_dundi.c:552
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:583

References ast_calloc, ast_copy_string(), ast_debug, ast_eid_cmp(), ast_eid_to_str(), ast_free, ast_log, ast_pthread_create_detached, dundi_ies::called_context, dundi_query_state::called_context, DUNDI_CAUSE_GENERAL, DUNDI_COMMAND_EIDRESPONSE, dundi_ie_append_cause(), DUNDI_IE_CAUSE, dundi_query_thread(), dundi_send(), dundi_ies::eidcount, dundi_ies::eids, dundi_query_state::eids, dundi_query_state::fluffy, LOG_WARNING, NULL, dundi_ies::reqeid, dundi_query_state::reqeid, dundi_transaction::thread, dundi_query_state::trans, dundi_ies::ttl, and dundi_query_state::ttl.

Referenced by handle_command_response().

◆ dundi_answer_query()

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

Definition at line 1087 of file pbx_dundi.c.

1088 {
1089  struct dundi_query_state *st;
1090  int totallen;
1091  int x;
1092  struct dundi_ie_data ied;
1093  char *s;
1094  struct dundi_mapping *cur;
1095  int mapcount = 0;
1096  int skipfirst = 0;
1097 
1098  pthread_t lookupthread;
1099  totallen = sizeof(struct dundi_query_state);
1100  /* Count matching map entries */
1101  AST_LIST_TRAVERSE(&mappings, cur, list) {
1102  if (!strcasecmp(cur->dcontext, ccontext))
1103  mapcount++;
1104  }
1105  /* If no maps, return -1 immediately */
1106  if (!mapcount)
1107  return -1;
1108 
1109  if (ies->eidcount > 1) {
1110  /* Since it is a requirement that the first EID is the authenticating host
1111  and the last EID is the root, it is permissible that the first and last EID
1112  could be the same. In that case, we should go ahead copy only the "root" section
1113  since we will not need it for authentication. */
1114  if (!ast_eid_cmp(ies->eids[0], ies->eids[ies->eidcount - 1]))
1115  skipfirst = 1;
1116  }
1117 
1118  totallen += mapcount * sizeof(struct dundi_mapping);
1119  totallen += (ies->eidcount - skipfirst) * sizeof(dundi_eid);
1120  st = ast_calloc(1, totallen);
1121  if (st) {
1123  ast_copy_string(st->called_number, ies->called_number, sizeof(st->called_number));
1124  st->trans = trans;
1125  st->ttl = ies->ttl - 1;
1126  st->nocache = ies->cbypass;
1127  if (st->ttl < 0)
1128  st->ttl = 0;
1129  s = st->fluffy;
1130  for (x=skipfirst;ies->eids[x];x++) {
1131  st->eids[x-skipfirst] = (dundi_eid *)s;
1132  *st->eids[x-skipfirst] = *ies->eids[x];
1133  st->directs[x-skipfirst] = ies->eid_direct[x];
1134  s += sizeof(dundi_eid);
1135  }
1136  /* Append mappings */
1137  x = 0;
1138  st->maps = (struct dundi_mapping *)s;
1139  AST_LIST_TRAVERSE(&mappings, cur, list) {
1140  if (!strcasecmp(cur->dcontext, ccontext)) {
1141  if (x < mapcount) {
1142  st->maps[x] = *cur;
1143  st->maps[x].list.next = NULL;
1144  x++;
1145  }
1146  }
1147  }
1148  st->nummaps = mapcount;
1149  ast_debug(1, "Answering query for '%s@%s'!\n", ies->called_number, ies->called_context);
1150  trans->thread = 1;
1151  if (ast_pthread_create_detached(&lookupthread, NULL, dundi_lookup_thread, st)) {
1152  trans->thread = 0;
1153  ast_log(LOG_WARNING, "Unable to create thread!\n");
1154  ast_free(st);
1155  memset(&ied, 0, sizeof(ied));
1156  dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of threads");
1157  dundi_send(trans, DUNDI_COMMAND_DPRESPONSE, 0, 1, &ied);
1158  return -1;
1159  }
1160  } else {
1161  ast_log(LOG_WARNING, "Out of memory!\n");
1162  memset(&ied, 0, sizeof(ied));
1163  dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of memory");
1164  dundi_send(trans, DUNDI_COMMAND_DPRESPONSE, 0, 1, &ied);
1165  return -1;
1166  }
1167  return 0;
1168 }
#define DUNDI_COMMAND_DPRESPONSE
Definition: dundi.h:161
static void * dundi_lookup_thread(void *data)
Definition: pbx_dundi.c:657
int eid_direct[DUNDI_MAX_STACK+1]
Definition: dundi-parser.h:23
char * called_number
Definition: dundi-parser.h:27
struct dundi_mapping * next
Definition: pbx_dundi.c:300
struct dundi_mapping * maps
Definition: pbx_dundi.c:549
int directs[DUNDI_MAX_STACK+1]
Definition: pbx_dundi.c:545
char called_number[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:548

References ast_calloc, ast_copy_string(), ast_debug, ast_eid_cmp(), ast_free, AST_LIST_TRAVERSE, ast_log, ast_pthread_create_detached, 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_ie_append_cause(), DUNDI_IE_CAUSE, dundi_lookup_thread(), dundi_send(), dundi_ies::eid_direct, dundi_ies::eidcount, dundi_ies::eids, dundi_query_state::eids, dundi_query_state::fluffy, dundi_mapping::list, LOG_WARNING, dundi_query_state::maps, dundi_mapping::next, dundi_query_state::nocache, NULL, dundi_query_state::nummaps, dundi_transaction::thread, dundi_query_state::trans, dundi_ies::ttl, and dundi_query_state::ttl.

Referenced by handle_command_response().

◆ dundi_canmatch()

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

4828 {
4829  return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_CANMATCH);
4830 }
static int priority
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:122
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:120
@ DUNDI_FLAG_CANMATCH
Definition: dundi.h:72
static int dundi_helper(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *data, int flag)
Definition: pbx_dundi.c:4783

References context, DUNDI_FLAG_CANMATCH, dundi_helper(), exten, and priority.

◆ dundi_debug_output()

static void dundi_debug_output ( const char *  data)
static

Definition at line 356 of file pbx_dundi.c.

357 {
358  if (dundidebug)
359  ast_verbose("%s", data);
360 }
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2206
static int dundidebug
Definition: pbx_dundi.c:192

References ast_verbose(), and dundidebug.

◆ dundi_decrypt()

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

Definition at line 1406 of file pbx_dundi.c.

1407 {
1408  int space = *dstlen;
1409  unsigned long bytes;
1410  struct dundi_hdr *h;
1411  unsigned char *decrypt_space;
1412  decrypt_space = ast_alloca(srclen);
1413  decrypt_memcpy(decrypt_space, src->encdata, srclen, src->iv, &trans->dcx);
1414  /* Setup header */
1415  h = (struct dundi_hdr *)dst;
1416  *h = *ohdr;
1417  bytes = space - 6;
1418  if (uncompress(dst + 6, &bytes, decrypt_space, srclen) != Z_OK) {
1419  ast_debug(1, "Ouch, uncompress failed :(\n");
1420  return NULL;
1421  }
1422  /* Update length */
1423  *dstlen = bytes + 6;
1424  /* Return new header */
1425  return h;
1426 }
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
static int decrypt_memcpy(unsigned char *dst, unsigned char *src, int len, unsigned char *iv, ast_aes_decrypt_key *dcx)
Definition: pbx_dundi.c:1389
unsigned char iv[16]
Definition: dundi.h:98
unsigned char encdata[0]
Definition: dundi.h:99
ast_aes_decrypt_key dcx
Definition: pbx_dundi.c:253

References ast_alloca, ast_debug, dundi_transaction::dcx, decrypt_memcpy(), dundi_encblock::encdata, dundi_encblock::iv, and NULL.

Referenced by handle_command_response().

◆ dundi_discover()

static int dundi_discover ( struct dundi_transaction trans)
static

Definition at line 3413 of file pbx_dundi.c.

3414 {
3415  struct dundi_ie_data ied;
3416  int x;
3417  if (!trans->parent) {
3418  ast_log(LOG_WARNING, "Tried to discover a transaction with no parent?!?\n");
3419  return -1;
3420  }
3421  memset(&ied, 0, sizeof(ied));
3423  if (!dundi_eid_zero(&trans->us_eid))
3425  for (x=0;x<trans->eidcount;x++)
3426  dundi_ie_append_eid_appropriately(&ied, trans->parent->dcontext, &trans->eids[x], &trans->us_eid);
3429  dundi_ie_append_short(&ied, DUNDI_IE_TTL, trans->ttl);
3430  if (trans->parent->cbypass)
3432  if (trans->autokilltimeout)
3433  trans->autokillid = ast_sched_add(sched, trans->autokilltimeout, do_autokill, trans);
3434  return dundi_send(trans, DUNDI_COMMAND_DPDISCOVER, 0, 0, &ied);
3435 }
int dundi_ie_append(struct dundi_ie_data *ied, unsigned char ie)
Definition: dundi-parser.c:620
int dundi_ie_append_str(struct dundi_ie_data *ied, unsigned char ie, char *str)
Definition: dundi-parser.c:605
#define DUNDI_IE_CACHEBYPASS
Definition: dundi.h:207
#define DUNDI_IE_TTL
Definition: dundi.h:187
#define DUNDI_IE_CALLED_CONTEXT
Definition: dundi.h:183
#define DUNDI_IE_CALLED_NUMBER
Definition: dundi.h:184
#define DUNDI_IE_EID_DIRECT
Definition: dundi.h:185
#define DUNDI_COMMAND_DPDISCOVER
Definition: dundi.h:160
static void dundi_ie_append_eid_appropriately(struct dundi_ie_data *ied, char *context, dundi_eid *eid, dundi_eid *us)
Definition: pbx_dundi.c:3391
static int do_autokill(const void *data)
Definition: pbx_dundi.c:3380

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

◆ dundi_do_lookup()

static char* dundi_do_lookup ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 2456 of file pbx_dundi.c.

2457 {
2458  int res;
2459  char tmp[256];
2460  char fs[80] = "";
2461  char *context;
2462  int x;
2463  int bypass = 0;
2464  struct dundi_result dr[MAX_RESULTS];
2465  struct timeval start;
2466  switch (cmd) {
2467  case CLI_INIT:
2468  e->command = "dundi lookup";
2469  e->usage =
2470  "Usage: dundi lookup <number>[@context] [bypass]\n"
2471  " Lookup the given number within the given DUNDi context\n"
2472  "(or e164 if none is specified). Bypasses cache if 'bypass'\n"
2473  "keyword is specified.\n";
2474  return NULL;
2475  case CLI_GENERATE:
2476  return NULL;
2477  }
2478 
2479  if ((a->argc < 3) || (a->argc > 4)) {
2480  return CLI_SHOWUSAGE;
2481  }
2482  if (a->argc > 3) {
2483  if (!strcasecmp(a->argv[3], "bypass")) {
2484  bypass=1;
2485  } else {
2486  return CLI_SHOWUSAGE;
2487  }
2488  }
2489  ast_copy_string(tmp, a->argv[2], sizeof(tmp));
2490  context = strchr(tmp, '@');
2491  if (context) {
2492  *context = '\0';
2493  context++;
2494  }
2495  start = ast_tvnow();
2496  res = dundi_lookup(dr, MAX_RESULTS, NULL, context, tmp, bypass);
2497 
2498  if (res < 0)
2499  ast_cli(a->fd, "DUNDi lookup returned error.\n");
2500  else if (!res)
2501  ast_cli(a->fd, "DUNDi lookup returned no results.\n");
2502  else
2503  sort_results(dr, res);
2504  for (x=0;x<res;x++) {
2505  ast_cli(a->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));
2506  ast_cli(a->fd, " from %s, expires in %d s\n", dr[x].eid_str, dr[x].expiration);
2507  }
2508  ast_cli(a->fd, "DUNDi lookup completed in %" PRIi64 " ms\n", ast_tvdiff_ms(ast_tvnow(), start));
2509  return CLI_SUCCESS;
2510 }
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define MAX_RESULTS
Definition: pbx_dundi.c:153
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. Lookup number in a given dundi context (if unspec...
Definition: pbx_dundi.c:3926
static void sort_results(struct dundi_result *results, int count)
Definition: pbx_dundi.c:2451
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
static struct test_val a

References a, ast_cli(), ast_copy_string(), ast_tvdiff_ms(), ast_tvnow(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, context, dr, dundi_flags2str(), dundi_lookup(), MAX_RESULTS, NULL, sort_results(), tmp(), and ast_cli_entry::usage.

◆ dundi_do_precache()

static char* dundi_do_precache ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 2512 of file pbx_dundi.c.

2513 {
2514  int res;
2515  char tmp[256];
2516  char *context;
2517  struct timeval start;
2518  switch (cmd) {
2519  case CLI_INIT:
2520  e->command = "dundi precache";
2521  e->usage =
2522  "Usage: dundi precache <number>[@context]\n"
2523  " Lookup the given number within the given DUNDi context\n"
2524  "(or e164 if none is specified) and precaches the results to any\n"
2525  "upstream DUNDi push servers.\n";
2526  return NULL;
2527  case CLI_GENERATE:
2528  return NULL;
2529  }
2530  if ((a->argc < 3) || (a->argc > 3)) {
2531  return CLI_SHOWUSAGE;
2532  }
2533  ast_copy_string(tmp, a->argv[2], sizeof(tmp));
2534  context = strchr(tmp, '@');
2535  if (context) {
2536  *context = '\0';
2537  context++;
2538  }
2539  start = ast_tvnow();
2540  res = dundi_precache(context, tmp);
2541 
2542  if (res < 0)
2543  ast_cli(a->fd, "DUNDi precache returned error.\n");
2544  else if (!res)
2545  ast_cli(a->fd, "DUNDi precache returned no error.\n");
2546  ast_cli(a->fd, "DUNDi lookup completed in %" PRIi64 " ms\n", ast_tvdiff_ms(ast_tvnow(), start));
2547  return CLI_SUCCESS;
2548 }
int dundi_precache(const char *context, const char *number)
Pre-cache to push upstream peers.
Definition: pbx_dundi.c:4068

References a, ast_cli(), ast_copy_string(), ast_tvdiff_ms(), ast_tvnow(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, context, dundi_precache(), NULL, tmp(), and ast_cli_entry::usage.

◆ dundi_do_query()

static char* dundi_do_query ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 2550 of file pbx_dundi.c.

2551 {
2552  int res;
2553  char tmp[256];
2554  char *context;
2555  dundi_eid eid;
2556  struct dundi_entity_info dei;
2557  switch (cmd) {
2558  case CLI_INIT:
2559  e->command = "dundi query";
2560  e->usage =
2561  "Usage: dundi query <entity>[@context]\n"
2562  " Attempts to retrieve contact information for a specific\n"
2563  "DUNDi entity identifier (EID) within a given DUNDi context (or\n"
2564  "e164 if none is specified).\n";
2565  return NULL;
2566  case CLI_GENERATE:
2567  return NULL;
2568  }
2569  if ((a->argc < 3) || (a->argc > 3)) {
2570  return CLI_SHOWUSAGE;
2571  }
2572  if (ast_str_to_eid(&eid, a->argv[2])) {
2573  ast_cli(a->fd, "'%s' is not a valid EID!\n", a->argv[2]);
2574  return CLI_SHOWUSAGE;
2575  }
2576  ast_copy_string(tmp, a->argv[2], sizeof(tmp));
2577  context = strchr(tmp, '@');
2578  if (context) {
2579  *context = '\0';
2580  context++;
2581  }
2582  res = dundi_query_eid(&dei, context, eid);
2583  if (res < 0)
2584  ast_cli(a->fd, "DUNDi Query EID returned error.\n");
2585  else if (!res)
2586  ast_cli(a->fd, "DUNDi Query EID returned no results.\n");
2587  else {
2588  ast_cli(a->fd, "DUNDi Query EID succeeded:\n");
2589  ast_cli(a->fd, "Department: %s\n", dei.orgunit);
2590  ast_cli(a->fd, "Organization: %s\n", dei.org);
2591  ast_cli(a->fd, "City/Locality: %s\n", dei.locality);
2592  ast_cli(a->fd, "State/Province: %s\n", dei.stateprov);
2593  ast_cli(a->fd, "Country: %s\n", dei.country);
2594  ast_cli(a->fd, "E-mail: %s\n", dei.email);
2595  ast_cli(a->fd, "Phone: %s\n", dei.phone);
2596  ast_cli(a->fd, "IP Address: %s\n", dei.ipaddr);
2597  }
2598  return CLI_SUCCESS;
2599 }
int dundi_query_eid(struct dundi_entity_info *dei, const char *dcontext, dundi_eid eid)
Retrieve information on a specific EID.
Definition: pbx_dundi.c:4121

References a, ast_cli(), ast_copy_string(), ast_str_to_eid(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, context, dundi_entity_info::country, dundi_query_eid(), dundi_entity_info::email, dundi_entity_info::ipaddr, dundi_entity_info::locality, NULL, dundi_entity_info::org, dundi_entity_info::orgunit, dundi_entity_info::phone, dundi_entity_info::stateprov, tmp(), and ast_cli_entry::usage.

◆ dundi_encrypt()

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

Definition at line 1428 of file pbx_dundi.c.

1429 {
1430  unsigned char *compress_space;
1431  int len;
1432  int res;
1433  unsigned long bytes;
1434  struct dundi_ie_data ied;
1435  struct dundi_peer *peer;
1436  unsigned char iv[16];
1437  len = pack->datalen + pack->datalen / 100 + 42;
1438  compress_space = ast_alloca(len);
1439  memset(compress_space, 0, len);
1440  /* We care about everthing save the first 6 bytes of header */
1441  bytes = len;
1442  res = compress(compress_space, &bytes, pack->data + 6, pack->datalen - 6);
1443  if (res != Z_OK) {
1444  ast_debug(1, "Ouch, compression failed!\n");
1445  return -1;
1446  }
1447  memset(&ied, 0, sizeof(ied));
1448  /* Say who we are */
1449  if (!pack->h->iseqno && !pack->h->oseqno) {
1450  /* Need the key in the first copy */
1451  if (!(peer = find_peer(&trans->them_eid)))
1452  return -1;
1453  if (update_key(peer))
1454  return -1;
1455  if (!peer->sentfullkey)
1457  /* Append key data */
1458  dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid);
1459  if (ast_test_flag(trans, FLAG_SENDFULLKEY)) {
1460  dundi_ie_append_raw(&ied, DUNDI_IE_SHAREDKEY, peer->txenckey, 128);
1461  dundi_ie_append_raw(&ied, DUNDI_IE_SIGNATURE, peer->txenckey + 128, 128);
1462  } else {
1464  }
1465  /* Setup contexts */
1466  trans->ecx = peer->us_ecx;
1467  trans->dcx = peer->us_dcx;
1468 
1469  /* We've sent the full key */
1470  peer->sentfullkey = 1;
1471  }
1472  /* Build initialization vector */
1473  build_iv(iv);
1474  /* Add the field, rounded up to 16 bytes */
1475  dundi_ie_append_encdata(&ied, DUNDI_IE_ENCDATA, iv, NULL, ((bytes + 15) / 16) * 16);
1476  /* Copy the data */
1477  if ((ied.pos + bytes) >= sizeof(ied.buf)) {
1478  ast_log(LOG_NOTICE, "Final packet too large!\n");
1479  return -1;
1480  }
1481  encrypt_memcpy(ied.buf + ied.pos, compress_space, bytes, iv, &trans->ecx);
1482  ied.pos += ((bytes + 15) / 16) * 16;
1483  /* Reconstruct header */
1484  pack->datalen = sizeof(struct dundi_hdr);
1485  pack->h->cmdresp = DUNDI_COMMAND_ENCRYPT;
1486  pack->h->cmdflags = 0;
1487  memcpy(pack->h->ies, ied.buf, ied.pos);
1488  pack->datalen += ied.pos;
1489  return 0;
1490 }
int dundi_ie_append_int(struct dundi_ie_data *ied, unsigned char ie, unsigned int value)
Definition: dundi-parser.c:591
int dundi_ie_append_encdata(struct dundi_ie_data *ied, unsigned char ie, unsigned char *iv, void *data, int datalen)
Definition: dundi-parser.c:539
int dundi_ie_append_raw(struct dundi_ie_data *ied, unsigned char ie, void *data, int datalen)
Definition: dundi-parser.c:484
#define DUNDI_IE_ENCDATA
Definition: dundi.h:193
#define DUNDI_IE_SIGNATURE
Definition: dundi.h:195
#define DUNDI_IE_SHAREDKEY
Definition: dundi.h:194
#define DUNDI_IE_KEYCRC32
Definition: dundi.h:196
#define DUNDI_COMMAND_ENCRYPT
Definition: dundi.h:172
static int encrypt_memcpy(unsigned char *dst, unsigned char *src, int len, unsigned char *iv, ast_aes_encrypt_key *ecx)
Definition: pbx_dundi.c:1373
static struct dundi_peer * find_peer(dundi_eid *eid)
Definition: pbx_dundi.c:515
static int update_key(struct dundi_peer *peer)
Definition: pbx_dundi.c:1334
unsigned char ies[0]
Definition: dundi.h:41
unsigned char cmdflags
Definition: dundi.h:40
unsigned char cmdresp
Definition: dundi.h:39
unsigned char iseqno
Definition: dundi.h:37
unsigned char data[0]
Definition: pbx_dundi.c:228
unsigned char txenckey[256]
Definition: pbx_dundi.c:316
uint32_t us_keycrc32
Definition: pbx_dundi.c:318
ast_aes_encrypt_key us_ecx
Definition: pbx_dundi.c:319
ast_aes_decrypt_key us_dcx
Definition: pbx_dundi.c:320
ast_aes_encrypt_key ecx
Definition: pbx_dundi.c:252

References ast_alloca, ast_debug, 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, len(), LOG_NOTICE, NULL, 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().

◆ dundi_error_output()

static void dundi_error_output ( const char *  data)
static

Definition at line 362 of file pbx_dundi.c.

363 {
364  ast_log(LOG_WARNING, "%s", data);
365 }

References ast_log, and LOG_WARNING.

◆ dundi_exec()

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

Definition at line 4832 of file pbx_dundi.c.

4833 {
4834  struct dundi_result results[MAX_RESULTS];
4835  int res;
4836  int x=0;
4837  char req[1024];
4838  const char *dundiargs;
4839  struct ast_app *dial;
4840 
4841  if (!strncasecmp(context, "macro-", 6)) {
4842  if (!chan) {
4843  ast_log(LOG_NOTICE, "Can't use macro mode without a channel!\n");
4844  return -1;
4845  }
4846  /* If done as a macro, use macro extension */
4847  if (!strcasecmp(exten, "s")) {
4848  exten = pbx_builtin_getvar_helper(chan, "ARG1");
4849  if (ast_strlen_zero(exten))
4850  exten = ast_channel_macroexten(chan);
4851  if (ast_strlen_zero(exten))
4852  exten = ast_channel_exten(chan);
4853  if (ast_strlen_zero(exten)) {
4854  ast_log(LOG_WARNING, "Called in Macro mode with no ARG1 or MACRO_EXTEN?\n");
4855  return -1;
4856  }
4857  }
4858  if (ast_strlen_zero(data))
4859  data = "e164";
4860  } else {
4861  if (ast_strlen_zero(data))
4862  data = context;
4863  }
4864  res = dundi_lookup(results, MAX_RESULTS, chan, data, exten, 0);
4865  if (res > 0) {
4866  sort_results(results, res);
4867  for (x=0;x<res;x++) {
4868  if (ast_test_flag(results + x, DUNDI_FLAG_EXISTS)) {
4869  if (!--priority)
4870  break;
4871  }
4872  }
4873  }
4874  if (x < res) {
4875  /* Got a hit! */
4876  dundiargs = pbx_builtin_getvar_helper(chan, "DUNDIDIALARGS");
4877  snprintf(req, sizeof(req), "%s/%s,,%s", results[x].tech, results[x].dest,
4878  S_OR(dundiargs, ""));
4879  dial = pbx_findapp("Dial");
4880  if (dial)
4881  res = pbx_exec(chan, dial, req);
4882  } else
4883  res = -1;
4884  return res;
4885 }
const char * ast_channel_exten(const struct ast_channel *chan)
const char * ast_channel_macroexten(const struct ast_channel *chan)
@ DUNDI_FLAG_EXISTS
Definition: dundi.h:68
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition: pbx_app.c:471
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition: ael_main.c:165
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
ast_app: A registered application
Definition: pbx_app.c:45

References ast_channel_exten(), ast_channel_macroexten(), ast_log, ast_strlen_zero(), ast_test_flag, context, DUNDI_FLAG_EXISTS, dundi_lookup(), exten, LOG_NOTICE, LOG_WARNING, MAX_RESULTS, pbx_builtin_getvar_helper(), pbx_exec(), pbx_findapp(), priority, S_OR, and sort_results().

◆ dundi_exists()

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

4823 {
4824  return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_EXISTS);
4825 }

References context, DUNDI_FLAG_EXISTS, dundi_helper(), exten, and priority.

◆ dundi_flush()

static char* dundi_flush ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 2357 of file pbx_dundi.c.

2358 {
2359  int stats = 0;
2360  switch (cmd) {
2361  case CLI_INIT:
2362  e->command = "dundi flush [stats]";
2363  e->usage =
2364  "Usage: dundi flush [stats]\n"
2365  " Flushes DUNDi answer cache, used primarily for debug. If\n"
2366  "'stats' is present, clears timer statistics instead of normal\n"
2367  "operation.\n";
2368  return NULL;
2369  case CLI_GENERATE:
2370  return NULL;
2371  }
2372  if ((a->argc < 2) || (a->argc > 3)) {
2373  return CLI_SHOWUSAGE;
2374  }
2375  if (a->argc > 2) {
2376  if (!strcasecmp(a->argv[2], "stats")) {
2377  stats = 1;
2378  } else {
2379  return CLI_SHOWUSAGE;
2380  }
2381  }
2382  if (stats) {
2383  /* Flush statistics */
2384  struct dundi_peer *p;
2385  int x;
2386  AST_LIST_LOCK(&peers);
2387  AST_LIST_TRAVERSE(&peers, p, list) {
2388  for (x = 0;x < DUNDI_TIMING_HISTORY; x++) {
2389  ast_free(p->lookups[x]);
2390  p->lookups[x] = NULL;
2391  p->lookuptimes[x] = 0;
2392  }
2393  p->avgms = 0;
2394  }
2396  } else {
2397  ast_db_deltree("dundi/cache", NULL);
2398  ast_cli(a->fd, "DUNDi Cache Flushed\n");
2399  }
2400  return CLI_SUCCESS;
2401 }
int ast_db_deltree(const char *family, const char *keytree)
Delete one or more entries in astdb.
Definition: main/db.c:457

References a, ast_cli(), ast_db_deltree(), ast_free, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, dundi_peer::avgms, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, DUNDI_TIMING_HISTORY, dundi_peer::list, dundi_peer::lookups, dundi_peer::lookuptimes, NULL, and ast_cli_entry::usage.

◆ dundi_helper()

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

4784 {
4785  struct dundi_result results[MAX_RESULTS];
4786  int res;
4787  int x;
4788  int found = 0;
4789  if (!strncasecmp(context, "macro-", 6)) {
4790  if (!chan) {
4791  ast_log(LOG_NOTICE, "Can't use macro mode without a channel!\n");
4792  return -1;
4793  }
4794  /* If done as a macro, use macro extension */
4795  if (!strcasecmp(exten, "s")) {
4796  exten = pbx_builtin_getvar_helper(chan, "ARG1");
4797  if (ast_strlen_zero(exten))
4798  exten = ast_channel_macroexten(chan);
4799  if (ast_strlen_zero(exten))
4800  exten = ast_channel_exten(chan);
4801  if (ast_strlen_zero(exten)) {
4802  ast_log(LOG_WARNING, "Called in Macro mode with no ARG1 or MACRO_EXTEN?\n");
4803  return -1;
4804  }
4805  }
4806  if (ast_strlen_zero(data))
4807  data = "e164";
4808  } else {
4809  if (ast_strlen_zero(data))
4810  data = context;
4811  }
4812  res = dundi_lookup(results, MAX_RESULTS, chan, data, exten, 0);
4813  for (x=0;x<res;x++) {
4814  if (ast_test_flag(results + x, flag))
4815  found++;
4816  }
4817  if (found >= priority)
4818  return 1;
4819  return 0;
4820 }
long int flag
Definition: f2c.h:83

References ast_channel_exten(), ast_channel_macroexten(), ast_log, ast_strlen_zero(), ast_test_flag, context, dundi_lookup(), exten, LOG_NOTICE, LOG_WARNING, MAX_RESULTS, pbx_builtin_getvar_helper(), and priority.

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

◆ dundi_ie_append_eid_appropriately()

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

Definition at line 3391 of file pbx_dundi.c.

3392 {
3393  struct dundi_peer *p;
3394  if (!ast_eid_cmp(eid, us)) {
3396  return;
3397  }
3398  AST_LIST_LOCK(&peers);
3399  AST_LIST_TRAVERSE(&peers, p, list) {
3400  if (!ast_eid_cmp(&p->eid, eid)) {
3401  if (has_permission(&p->include, context))
3403  else
3405  break;
3406  }
3407  }
3408  if (!p)
3411 }

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

Referenced by dundi_discover().

◆ dundi_lookup()

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

Lookup the given number in the given dundi context. Lookup number in a given dundi context (if unspecified use e164), the given callerid (if specified) and return up to maxret results in the array specified.

Return values
thenumber of results found.
-1on a hangup of the channel.

Definition at line 3926 of file pbx_dundi.c.

3927 {
3928  struct dundi_hint_metadata hmd;
3929  dundi_eid *avoid[1] = { NULL, };
3930  int direct[1] = { 0, };
3931  int expiration = dundi_cache_time;
3932  memset(&hmd, 0, sizeof(hmd));
3934  return dundi_lookup_internal(result, maxret, chan, dcontext, number, dundi_ttl, 0, &hmd, &expiration, cbypass, 0, NULL, avoid, direct);
3935 }
static PGresult * result
Definition: cel_pgsql.c:84
static int dundi_ttl
Definition: pbx_dundi.c:194
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[])
Definition: pbx_dundi.c:3824
Number structure.
Definition: app_followme.c:154

References dundi_cache_time, DUNDI_HINT_DONT_ASK, DUNDI_HINT_UNAFFECTED, dundi_lookup_internal(), dundi_ttl, dundi_hint_metadata::flags, NULL, and result.

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

◆ dundi_lookup_internal()

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

3825 {
3826  int res;
3827  struct dundi_request dr, *pending;
3828  dundi_eid *rooteid=NULL;
3829  int x;
3830  int ttlms;
3831  int ms;
3832  int foundcache;
3833  int skipped=0;
3834  int order=0;
3835  char eid_str[20];
3836  struct timeval start;
3837 
3838  /* Don't do anthing for a hungup channel */
3839  if (chan && ast_check_hangup(chan))
3840  return 0;
3841 
3842  ttlms = DUNDI_FLUFF_TIME + ttl * DUNDI_TTL_TIME;
3843 
3844  for (x=0;avoid[x];x++)
3845  rooteid = avoid[x];
3846  /* Now perform real check */
3847  memset(&dr, 0, sizeof(dr));
3848  if (pipe(dr.pfds)) {
3849  ast_log(LOG_WARNING, "pipe failed: %s\n" , strerror(errno));
3850  return -1;
3851  }
3852  dr.dr = result;
3853  dr.hmd = hmd;
3854  dr.maxcount = maxret;
3855  dr.expiration = *expiration;
3856  dr.cbypass = cbypass;
3857  dr.crc32 = avoid_crc32(avoid);
3858  ast_copy_string(dr.dcontext, dcontext ? dcontext : "e164", sizeof(dr.dcontext));
3859  ast_copy_string(dr.number, number, sizeof(dr.number));
3860  if (rooteid)
3861  dr.root_eid = *rooteid;
3862  res = register_request(&dr, &pending);
3863  if (res) {
3864  /* Already a request */
3865  if (rooteid && !ast_eid_cmp(&dr.root_eid, &pending->root_eid)) {
3866  /* This is on behalf of someone else. Go ahead and close this out since
3867  they'll get their answer anyway. */
3868  ast_debug(1, "Oooh, duplicate request for '%s@%s' for '%s'\n",
3869  dr.number,dr.dcontext,ast_eid_to_str(eid_str, sizeof(eid_str), &dr.root_eid));
3870  close(dr.pfds[0]);
3871  close(dr.pfds[1]);
3872  return -2;
3873  } else {
3874  /* Wait for the cache to populate */
3875  ast_debug(1, "Waiting for similar request for '%s@%s' for '%s'\n",
3876  dr.number,dr.dcontext,ast_eid_to_str(eid_str, sizeof(eid_str), &pending->root_eid));
3877  start = ast_tvnow();
3878  while(check_request(pending) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms) && (!chan || !ast_check_hangup(chan))) {
3879  /* XXX Would be nice to have a way to poll/select here XXX */
3880  /* XXX this is a busy wait loop!!! */
3881  usleep(1);
3882  }
3883  /* Continue on as normal, our cache should kick in */
3884  }
3885  }
3886  /* Create transactions */
3887  do {
3888  order = skipped;
3889  skipped = 0;
3890  foundcache = 0;
3891  build_transactions(&dr, ttl, order, &foundcache, &skipped, blockempty, cbypass, modeselect, skip, avoid, direct);
3892  } while (skipped && !foundcache && AST_LIST_EMPTY(&dr.trans));
3893  /* If no TTL, abort and return 0 now after setting TTL expired hint. Couldn't
3894  do this earlier because we didn't know if we were going to have transactions
3895  or not. */
3896  if (!ttl) {
3898  abort_request(&dr);
3900  close(dr.pfds[0]);
3901  close(dr.pfds[1]);
3902  return 0;
3903  }
3904 
3905  /* Optimize transactions */
3907  /* Actually perform transactions */
3909  /* Wait for transaction to come back */
3910  start = ast_tvnow();
3911  while (!AST_LIST_EMPTY(&dr.trans) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms) && (!chan || !ast_check_hangup(chan))) {
3912  ms = 100;
3913  ast_waitfor_n_fd(dr.pfds, 1, &ms, NULL);
3914  }
3915  if (chan && ast_check_hangup(chan))
3916  ast_debug(1, "Hrm, '%s' hungup before their query for %s@%s finished\n", ast_channel_name(chan), dr.number, dr.dcontext);
3917  cancel_request(&dr);
3919  res = dr.respcount;
3920  *expiration = dr.expiration;
3921  close(dr.pfds[0]);
3922  close(dr.pfds[1]);
3923  return res;
3924 }
int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception)
Waits for input on an fd.
Definition: channel.c:2981
const char * ast_channel_name(const struct ast_channel *chan)
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
#define DUNDI_FLUFF_TIME
Definition: dundi.h:211
#define DUNDI_TTL_TIME
Definition: dundi.h:212
@ DUNDI_HINT_TTL_EXPIRED
Definition: dundi.h:90
static void cancel_request(struct dundi_request *dr)
Definition: pbx_dundi.c:3674
static int optimize_transactions(struct dundi_request *dr, int order)
Definition: pbx_dundi.c:3584
static int check_request(struct dundi_request *dr)
Definition: pbx_dundi.c:3795
static unsigned long avoid_crc32(dundi_eid *avoid[])
Definition: pbx_dundi.c:3809
static int register_request(struct dundi_request *dr, struct dundi_request **pending)
Definition: pbx_dundi.c:3758
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[])
Definition: pbx_dundi.c:3700
static void unregister_request(struct dundi_request *dr)
Definition: pbx_dundi.c:3788
static void abort_request(struct dundi_request *dr)
Definition: pbx_dundi.c:3688
static int discover_transactions(struct dundi_request *dr)
Definition: pbx_dundi.c:3525
#define ast_set_flag_nonstd(p, flag)
Definition: utils.h:176

References abort_request(), ast_channel_name(), ast_check_hangup(), ast_copy_string(), ast_debug, ast_eid_cmp(), ast_eid_to_str(), AST_LIST_EMPTY, ast_log, ast_set_flag_nonstd, ast_tvdiff_ms(), ast_tvnow(), ast_waitfor_n_fd(), avoid_crc32(), build_transactions(), cancel_request(), check_request(), discover_transactions(), dr, DUNDI_FLUFF_TIME, DUNDI_HINT_TTL_EXPIRED, DUNDI_TTL_TIME, errno, LOG_WARNING, NULL, optimize_transactions(), order, register_request(), result, dundi_request::root_eid, and unregister_request().

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

◆ dundi_lookup_local()

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

579 {
580  struct ast_flags flags = {0};
581  int x;
582  if (!ast_strlen_zero(map->lcontext)) {
583  if (ast_exists_extension(NULL, map->lcontext, called_number, 1, NULL))
585  if (ast_canmatch_extension(NULL, map->lcontext, called_number, 1, NULL))
587  if (ast_matchmore_extension(NULL, map->lcontext, called_number, 1, NULL))
589  if (ast_ignore_pattern(map->lcontext, called_number))
591 
592  /* Clearly we can't say 'don't ask' anymore if we found anything... */
595 
597  /* Skip partial answers */
599  }
601  struct varshead headp;
602  struct ast_var_t *newvariable;
603  ast_set_flag(&flags, map->options & 0xffff);
604  ast_copy_flags(dr + anscnt, &flags, AST_FLAGS_ALL);
605  dr[anscnt].techint = map->tech;
606  dr[anscnt].expiration = dundi_cache_time;
607  ast_copy_string(dr[anscnt].tech, tech2str(map->tech), sizeof(dr[anscnt].tech));
608  dr[anscnt].eid = *us_eid;
609  ast_eid_to_str(dr[anscnt].eid_str, sizeof(dr[anscnt].eid_str), &dr[anscnt].eid);
610  if (ast_test_flag(&flags, DUNDI_FLAG_EXISTS)) {
612  if ((newvariable = ast_var_assign("NUMBER", called_number))) {
613  AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
614  }
615  if ((newvariable = ast_var_assign("EID", dr[anscnt].eid_str))) {
616  AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
617  }
618  if ((newvariable = ast_var_assign("SECRET", cursecret))) {
619  AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
620  }
621  if ((newvariable = ast_var_assign("IPADDR", ipaddr))) {
622  AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
623  }
624  pbx_substitute_variables_varshead(&headp, map->dest, dr[anscnt].dest, sizeof(dr[anscnt].dest));
625  dr[anscnt].weight = get_mapping_weight(map, &headp);
626  while ((newvariable = AST_LIST_REMOVE_HEAD(&headp, entries)))
627  ast_var_delete(newvariable);
628  } else {
629  dr[anscnt].dest[0] = '\0';
630  dr[anscnt].weight = get_mapping_weight(map, NULL);
631  }
632  anscnt++;
633  } else {
634  /* No answers... Find the fewest number of digits from the
635  number for which we have no answer. */
636  char tmp[AST_MAX_EXTENSION + 1] = "";
637  for (x = 0; x < (sizeof(tmp) - 1); x++) {
638  tmp[x] = called_number[x];
639  if (!tmp[x])
640  break;
641  if (!ast_canmatch_extension(NULL, map->lcontext, tmp, 1, NULL)) {
642  /* Oops found something we can't match. If this is longer
643  than the running hint, we have to consider it */
644  if (strlen(tmp) > strlen(hmd->exten)) {
645  ast_copy_string(hmd->exten, tmp, sizeof(hmd->exten));
646  }
647  break;
648  }
649  }
650  }
651  }
652  return anscnt;
653 }
#define AST_MAX_EXTENSION
Definition: channel.h:134
#define ast_var_assign(name, value)
Definition: chanvars.h:40
void ast_var_delete(struct ast_var_t *var)
Definition: extconf.c:2472
@ DUNDI_FLAG_MATCHMORE
Definition: dundi.h:70
@ DUNDI_FLAG_IGNOREPAT
Definition: dundi.h:74
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:681
void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count)
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:4182
int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks for a valid matching extension.
Definition: pbx.c:4197
int ast_ignore_pattern(const char *context, const char *pattern)
Checks to see if a number should be ignored.
int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks to see if adding anything to this extension might match something. (exists ^ canmatch)
Definition: pbx.c:4202
static int get_mapping_weight(struct dundi_mapping *map, struct varshead *headp)
Definition: pbx_dundi.c:559
static char ipaddr[80]
Definition: pbx_dundi.c:210
struct ast_var_t::@239 entries
#define ast_clear_flag(p, flag)
Definition: utils.h:77

References ast_canmatch_extension(), ast_clear_flag, ast_clear_flag_nonstd, ast_copy_flags, ast_copy_string(), ast_eid_to_str(), ast_exists_extension(), AST_FLAGS_ALL, ast_ignore_pattern(), AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_HEAD, ast_matchmore_extension(), AST_MAX_EXTENSION, ast_set_flag, ast_strlen_zero(), ast_test_flag, ast_var_assign, ast_var_delete(), cursecret, dundi_mapping::dest, dr, dundi_cache_time, DUNDI_FLAG_CANMATCH, DUNDI_FLAG_EXISTS, DUNDI_FLAG_IGNOREPAT, DUNDI_FLAG_INTERNAL_NOPARTIAL, DUNDI_FLAG_MATCHMORE, DUNDI_HINT_DONT_ASK, ast_var_t::entries, dundi_hint_metadata::exten, ast_flags::flags, get_mapping_weight(), ipaddr, dundi_mapping::lcontext, NULL, dundi_mapping::options, pbx_substitute_variables_varshead(), dundi_mapping::tech, tech2str(), and tmp().

Referenced by dundi_lookup_thread(), and precache_trans().

◆ dundi_lookup_thread()

static void* dundi_lookup_thread ( void *  data)
static

Definition at line 657 of file pbx_dundi.c.

658 {
659  struct dundi_query_state *st = data;
660  struct dundi_result dr[MAX_RESULTS];
661  struct dundi_ie_data ied;
662  struct dundi_hint_metadata hmd;
663  char eid_str[20];
664  int res, x;
665  int ouranswers=0;
666  int max = 999999;
667  int expiration = dundi_cache_time;
668 
669  ast_debug(1, "Whee, looking up '%s@%s' for '%s'\n", st->called_number, st->called_context,
670  st->eids[0] ? ast_eid_to_str(eid_str, sizeof(eid_str), st->eids[0]) : "ourselves");
671  memset(&ied, 0, sizeof(ied));
672  memset(&dr, 0, sizeof(dr));
673  memset(&hmd, 0, sizeof(hmd));
674  /* Assume 'don't ask for anything' and 'unaffected', no TTL expired */
676  for (x=0;x<st->nummaps;x++)
677  ouranswers = dundi_lookup_local(dr, st->maps + x, st->called_number, &st->trans->us_eid, ouranswers, &hmd);
678  if (ouranswers < 0)
679  ouranswers = 0;
680  for (x=0;x<ouranswers;x++) {
681  if (dr[x].weight < max)
682  max = dr[x].weight;
683  }
684 
685  if (max) {
686  /* If we do not have a canonical result, keep looking */
687  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);
688  if (res > 0) {
689  /* Append answer in result */
690  ouranswers += res;
691  } else {
692  if ((res < -1) && (!ouranswers))
693  dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_DUPLICATE, "Duplicate Request Pending");
694  }
695  }
697  /* Truncate if "don't ask" isn't present */
699  hmd.exten[0] = '\0';
700  if (ast_test_flag(st->trans, FLAG_DEAD)) {
701  ast_debug(1, "Our transaction went away!\n");
702  st->trans->thread = 0;
703  destroy_trans(st->trans, 0);
704  } else {
705  for (x=0;x<ouranswers;x++) {
706  /* Add answers */
707  if (dr[x].expiration && (expiration > dr[x].expiration))
708  expiration = dr[x].expiration;
709  dundi_ie_append_answer(&ied, DUNDI_IE_ANSWER, &dr[x].eid, dr[x].techint, dr[x].flags, dr[x].weight, dr[x].dest);
710  }
711  dundi_ie_append_hint(&ied, DUNDI_IE_HINT, hmd.flags, hmd.exten);
712  dundi_ie_append_short(&ied, DUNDI_IE_EXPIRATION, expiration);
713  dundi_send(st->trans, DUNDI_COMMAND_DPRESPONSE, 0, 1, &ied);
714  st->trans->thread = 0;
715  }
717  ast_free(st);
718  return NULL;
719 }
int dundi_ie_append_answer(struct dundi_ie_data *ied, unsigned char ie, dundi_eid *eid, unsigned char protocol, unsigned short flags, unsigned short weight, char *data)
Definition: dundi-parser.c:559
int dundi_ie_append_hint(struct dundi_ie_data *ied, unsigned char ie, unsigned short flags, char *data)
Definition: dundi-parser.c:518
#define DUNDI_IE_HINT
Definition: dundi.h:197
@ DUNDI_CAUSE_DUPLICATE
Definition: dundi.h:125
#define DUNDI_IE_ANSWER
Definition: dundi.h:186
#define max(a, b)
Definition: f2c.h:198
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)
Definition: pbx_dundi.c:578
unsigned short flags
Definition: pbx_dundi.c:232

References ast_debug, ast_eid_to_str(), ast_free, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_test_flag, ast_test_flag_nonstd, dundi_query_state::called_context, dundi_query_state::called_number, destroy_trans(), dundi_query_state::directs, dr, dundi_cache_time, DUNDI_CAUSE_DUPLICATE, DUNDI_COMMAND_DPRESPONSE, DUNDI_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_hint_metadata::exten, FLAG_DEAD, dundi_hint_metadata::flags, dundi_query_state::maps, max, MAX_RESULTS, dundi_query_state::nocache, NULL, dundi_query_state::nummaps, dundi_transaction::thread, dundi_query_state::trans, dundi_query_state::ttl, dundi_transaction::us_eid, and weight.

Referenced by dundi_answer_query().

◆ dundi_matchmore()

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

4888 {
4889  return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_MATCHMORE);
4890 }

References context, DUNDI_FLAG_MATCHMORE, dundi_helper(), exten, and priority.

◆ dundi_precache()

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

Pre-cache to push upstream peers.

Definition at line 4068 of file pbx_dundi.c.

4069 {
4070  dundi_eid *avoid[1] = { NULL, };
4072 }
static int dundi_precache_internal(const char *context, const char *number, int ttl, dundi_eid *avoids[])
Definition: pbx_dundi.c:3996

References context, dundi_precache_internal(), dundi_ttl, and NULL.

Referenced by dundi_do_precache(), and process_precache().

◆ dundi_precache_full()

static void dundi_precache_full ( void  )
static

Definition at line 3972 of file pbx_dundi.c.

3973 {
3974  struct dundi_mapping *cur;
3975  struct ast_context *con;
3976  struct ast_exten *e;
3977 
3978  AST_LIST_TRAVERSE(&mappings, cur, list) {
3979  ast_log(LOG_NOTICE, "Should precache context '%s'\n", cur->dcontext);
3981  con = NULL;
3982  while ((con = ast_walk_contexts(con))) {
3983  if (strcasecmp(cur->lcontext, ast_get_context_name(con)))
3984  continue;
3985  /* Found the match, now queue them all up */
3986  ast_rdlock_context(con);
3987  e = NULL;
3988  while ((e = ast_walk_context_extensions(con, e)))
3990  ast_unlock_context(con);
3991  }
3993  }
3994 }
struct ast_context * ast_walk_contexts(struct ast_context *con)
Definition: extconf.c:4025
const char * ast_get_extension_name(struct ast_exten *exten)
int ast_unlock_context(struct ast_context *con)
const char * ast_get_context_name(struct ast_context *con)
Definition: ael_main.c:421
int ast_rdlock_contexts(void)
Read locks the context list.
struct ast_exten * ast_walk_context_extensions(struct ast_context *con, struct ast_exten *priority)
Definition: ael_main.c:427
int ast_unlock_contexts(void)
Unlocks contexts.
int ast_rdlock_context(struct ast_context *con)
Read locks a given context.
static void reschedule_precache(const char *number, const char *context, int expiration)
Definition: pbx_dundi.c:3937
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own link...
Definition: pbx.c:237

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

Referenced by set_config().

◆ dundi_precache_internal()

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

Definition at line 3996 of file pbx_dundi.c.

3997 {
3998  struct dundi_request dr;
3999  struct dundi_hint_metadata hmd;
4000  struct dundi_result dr2[MAX_RESULTS];
4001  struct timeval start;
4002  struct dundi_mapping *maps = NULL, *cur;
4003  int nummaps = 0;
4004  int foundanswers;
4005  int foundcache, skipped, ttlms, ms;
4006  if (!context)
4007  context = "e164";
4008  ast_debug(1, "Precache internal (%s@%s)!\n", number, context);
4009 
4010  AST_LIST_LOCK(&peers);
4011  AST_LIST_TRAVERSE(&mappings, cur, list) {
4012  if (!strcasecmp(cur->dcontext, context))
4013  nummaps++;
4014  }
4015  if (nummaps) {
4016  maps = ast_alloca(nummaps * sizeof(*maps));
4017  nummaps = 0;
4018  AST_LIST_TRAVERSE(&mappings, cur, list) {
4019  if (!strcasecmp(cur->dcontext, context))
4020  maps[nummaps++] = *cur;
4021  }
4022  }
4024  if (!nummaps) {
4025  return -1;
4026  }
4027  ttlms = DUNDI_FLUFF_TIME + ttl * DUNDI_TTL_TIME;
4028  memset(&dr2, 0, sizeof(dr2));
4029  memset(&dr, 0, sizeof(dr));
4030  memset(&hmd, 0, sizeof(hmd));
4031  dr.dr = dr2;
4032  ast_copy_string(dr.number, number, sizeof(dr.number));
4033  ast_copy_string(dr.dcontext, context ? context : "e164", sizeof(dr.dcontext));
4034  dr.maxcount = MAX_RESULTS;
4035  dr.expiration = dundi_cache_time;
4036  dr.hmd = &hmd;
4037  dr.pfds[0] = dr.pfds[1] = -1;
4038  if (pipe(dr.pfds) < 0) {
4039  ast_log(LOG_WARNING, "pipe() failed: %s\n", strerror(errno));
4040  return -1;
4041  }
4042  build_transactions(&dr, ttl, 0, &foundcache, &skipped, 0, 1, 1, NULL, avoids, NULL);
4044  foundanswers = 0;
4045  precache_transactions(&dr, maps, nummaps, &dr.expiration, &foundanswers);
4046  if (foundanswers) {
4047  if (dr.expiration > 0)
4048  reschedule_precache(dr.number, dr.dcontext, dr.expiration);
4049  else
4050  ast_log(LOG_NOTICE, "Weird, expiration = %d, but need to precache for %s@%s?!\n", dr.expiration, dr.number, dr.dcontext);
4051  }
4052  start = ast_tvnow();
4053  while (!AST_LIST_EMPTY(&dr.trans) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms)) {
4054  if (dr.pfds[0] > -1) {
4055  ms = 100;
4056  ast_waitfor_n_fd(dr.pfds, 1, &ms, NULL);
4057  } else
4058  usleep(1);
4059  }
4060  cancel_request(&dr);
4061  if (dr.pfds[0] > -1) {
4062  close(dr.pfds[0]);
4063  close(dr.pfds[1]);
4064  }
4065  return 0;
4066 }
static int precache_transactions(struct dundi_request *dr, struct dundi_mapping *maps, int mapcount, int *expiration, int *foundanswers)
Definition: pbx_dundi.c:3536

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

Referenced by dundi_precache(), and dundi_precache_thread().

◆ dundi_precache_thread()

static void* dundi_precache_thread ( void *  data)
static

Definition at line 721 of file pbx_dundi.c.

722 {
723  struct dundi_query_state *st = data;
724  struct dundi_ie_data ied;
725  struct dundi_hint_metadata hmd = {0};
726  char eid_str[20];
727 
728  ast_debug(1, "Whee, precaching '%s@%s' for '%s'\n", st->called_number, st->called_context,
729  st->eids[0] ? ast_eid_to_str(eid_str, sizeof(eid_str), st->eids[0]) : "ourselves");
730  memset(&ied, 0, sizeof(ied));
731 
732  /* Now produce precache */
734 
736  /* Truncate if "don't ask" isn't present */
738  hmd.exten[0] = '\0';
739  if (ast_test_flag(st->trans, FLAG_DEAD)) {
740  ast_debug(1, "Our transaction went away!\n");
741  st->trans->thread = 0;
742  destroy_trans(st->trans, 0);
743  } else {
744  dundi_send(st->trans, DUNDI_COMMAND_PRECACHERP, 0, 1, &ied);
745  st->trans->thread = 0;
746  }
748  ast_free(st);
749  return NULL;
750 }
#define DUNDI_COMMAND_PRECACHERP
Definition: dundi.h:165

References ast_debug, ast_eid_to_str(), ast_free, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_test_flag, ast_test_flag_nonstd, dundi_query_state::called_context, dundi_query_state::called_number, destroy_trans(), DUNDI_COMMAND_PRECACHERP, DUNDI_HINT_DONT_ASK, dundi_precache_internal(), dundi_send(), dundi_query_state::eids, dundi_hint_metadata::exten, FLAG_DEAD, NULL, dundi_transaction::thread, dundi_query_state::trans, and dundi_query_state::ttl.

Referenced by dundi_prop_precache().

◆ dundi_prop_precache()

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

Definition at line 940 of file pbx_dundi.c.

941 {
942  struct dundi_query_state *st;
943  int totallen;
944  int x,z;
945  struct dundi_ie_data ied;
946  char *s;
947  struct dundi_result dr2[MAX_RESULTS];
948  struct dundi_request dr;
949  struct dundi_hint_metadata hmd;
950 
951  struct dundi_mapping *cur;
952  int mapcount;
953  int skipfirst = 0;
954 
955  pthread_t lookupthread;
956 
957  memset(&dr2, 0, sizeof(dr2));
958  memset(&dr, 0, sizeof(dr));
959  memset(&hmd, 0, sizeof(hmd));
960 
961  /* Forge request structure to hold answers for cache */
963  dr.dr = dr2;
964  dr.maxcount = MAX_RESULTS;
965  dr.expiration = dundi_cache_time;
966  dr.hmd = &hmd;
967  dr.pfds[0] = dr.pfds[1] = -1;
968  trans->parent = &dr;
969  ast_copy_string(dr.dcontext, ies->called_context ? ies->called_context : "e164", sizeof(dr.dcontext));
970  ast_copy_string(dr.number, ies->called_number, sizeof(dr.number));
971 
972  for (x=0;x<ies->anscount;x++) {
973  if (trans->parent->respcount < trans->parent->maxcount) {
974  /* Make sure it's not already there */
975  for (z=0;z<trans->parent->respcount;z++) {
976  if ((trans->parent->dr[z].techint == ies->answers[x]->protocol) &&
977  !strcmp(trans->parent->dr[z].dest, (char *)ies->answers[x]->data))
978  break;
979  }
980  if (z == trans->parent->respcount) {
981  /* Copy into parent responses */
982  trans->parent->dr[trans->parent->respcount].flags = ntohs(ies->answers[x]->flags);
983  trans->parent->dr[trans->parent->respcount].techint = ies->answers[x]->protocol;
984  trans->parent->dr[trans->parent->respcount].weight = ntohs(ies->answers[x]->weight);
985  trans->parent->dr[trans->parent->respcount].eid = ies->answers[x]->eid;
986  if (ies->expiration > 0)
987  trans->parent->dr[trans->parent->respcount].expiration = ies->expiration;
988  else
990  ast_eid_to_str(trans->parent->dr[trans->parent->respcount].eid_str,
991  sizeof(trans->parent->dr[trans->parent->respcount].eid_str),
992  &ies->answers[x]->eid);
993  ast_copy_string(trans->parent->dr[trans->parent->respcount].dest, (char *)ies->answers[x]->data,
994  sizeof(trans->parent->dr[trans->parent->respcount].dest));
995  ast_copy_string(trans->parent->dr[trans->parent->respcount].tech, tech2str(ies->answers[x]->protocol),
996  sizeof(trans->parent->dr[trans->parent->respcount].tech));
997  trans->parent->respcount++;
999  } else if (trans->parent->dr[z].weight > ntohs(ies->answers[x]->weight)) {
1000  /* Update weight if appropriate */
1001  trans->parent->dr[z].weight = ntohs(ies->answers[x]->weight);
1002  }
1003  } else
1004  ast_log(LOG_NOTICE, "Dropping excessive answers in precache for %s@%s\n",
1005  trans->parent->number, trans->parent->dcontext);
1006 
1007  }
1008  /* Save all the results (if any) we had. Even if no results, still cache lookup. */
1009  cache_save(&trans->them_eid, trans->parent, 0, 0, ies->expiration, 1);
1010  if (ies->hint)
1011  cache_save_hint(&trans->them_eid, trans->parent, ies->hint, ies->expiration);
1012 
1013  totallen = sizeof(struct dundi_query_state);
1014  /* Count matching map entries */
1015  mapcount = 0;
1016  AST_LIST_TRAVERSE(&mappings, cur, list) {
1017  if (!strcasecmp(cur->dcontext, ccontext))
1018  mapcount++;
1019  }
1020 
1021  /* If no maps, return -1 immediately */
1022  if (!mapcount)
1023  return -1;
1024 
1025  if (ies->eidcount > 1) {
1026  /* Since it is a requirement that the first EID is the authenticating host
1027  and the last EID is the root, it is permissible that the first and last EID
1028  could be the same. In that case, we should go ahead copy only the "root" section
1029  since we will not need it for authentication. */
1030  if (!ast_eid_cmp(ies->eids[0], ies->eids[ies->eidcount - 1]))
1031  skipfirst = 1;
1032  }
1033 
1034  /* Prepare to run a query and then propagate that as necessary */
1035  totallen += mapcount * sizeof(struct dundi_mapping);
1036  totallen += (ies->eidcount - skipfirst) * sizeof(dundi_eid);
1037  st = ast_calloc(1, totallen);
1038  if (st) {
1039  ast_copy_string(st->called_context, dr.dcontext, sizeof(st->called_context));
1040  ast_copy_string(st->called_number, ies->called_number, sizeof(st->called_number));
1041  st->trans = trans;
1042  st->ttl = ies->ttl - 1;
1043  st->nocache = ies->cbypass;
1044  if (st->ttl < 0)
1045  st->ttl = 0;
1046  s = st->fluffy;
1047  for (x=skipfirst;ies->eids[x];x++) {
1048  st->eids[x-skipfirst] = (dundi_eid *)s;
1049  *st->eids[x-skipfirst] = *ies->eids[x];
1050  st->directs[x-skipfirst] = ies->eid_direct[x];
1051  s += sizeof(dundi_eid);
1052  }
1053  /* Append mappings */
1054  x = 0;
1055  st->maps = (struct dundi_mapping *)s;
1056  AST_LIST_TRAVERSE(&mappings, cur, list) {
1057  if (!strcasecmp(cur->dcontext, ccontext)) {
1058  if (x < mapcount) {
1059  st->maps[x] = *cur;
1060  st->maps[x].list.next = NULL;
1061  x++;
1062  }
1063  }
1064  }
1065  st->nummaps = mapcount;
1066  ast_debug(1, "Forwarding precache for '%s@%s'!\n", ies->called_number, ies->called_context);
1067  trans->thread = 1;
1068  if (ast_pthread_create_detached(&lookupthread, NULL, dundi_precache_thread, st)) {
1069  trans->thread = 0;
1070  ast_log(LOG_WARNING, "Unable to create thread!\n");
1071  ast_free(st);
1072  memset(&ied, 0, sizeof(ied));
1073  dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of threads");
1074  dundi_send(trans, DUNDI_COMMAND_PRECACHERP, 0, 1, &ied);
1075  return -1;
1076  }
1077  } else {
1078  ast_log(LOG_WARNING, "Out of memory!\n");
1079  memset(&ied, 0, sizeof(ied));
1080  dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of memory");
1081  dundi_send(trans, DUNDI_COMMAND_PRECACHERP, 0, 1, &ied);
1082  return -1;
1083  }
1084  return 0;
1085 }
static int cache_save_hint(dundi_eid *eidpeer, struct dundi_request *req, struct dundi_hint *hint, int expiration)
Definition: pbx_dundi.c:864
static void * dundi_precache_thread(void *data)
Definition: pbx_dundi.c:721
static int cache_save(dundi_eid *eidpeer, struct dundi_request *req, int start, int unaffected, int expiration, int push)
Definition: pbx_dundi.c:899
unsigned short flags
Definition: dundi.h:105
unsigned short weight
Definition: dundi.h:106
unsigned char protocol
Definition: dundi.h:104
unsigned char data[0]
Definition: dundi.h:107
dundi_eid eid
Definition: dundi.h:103
struct dundi_answer * answers[DUNDI_MAX_ANSWERS+1]
Definition: dundi-parser.h:28
struct dundi_hint * hint
Definition: dundi-parser.h:29
int anscount
Definition: dundi-parser.h:30
int expiration
Definition: dundi-parser.h:33

References dundi_ies::anscount, dundi_ies::answers, ast_calloc, ast_clear_flag_nonstd, ast_copy_string(), ast_debug, ast_eid_cmp(), ast_eid_to_str(), ast_free, AST_LIST_TRAVERSE, ast_log, ast_pthread_create_detached, cache_save(), cache_save_hint(), dundi_ies::called_context, dundi_query_state::called_context, dundi_ies::called_number, dundi_query_state::called_number, dundi_ies::cbypass, dundi_answer::data, dundi_request::dcontext, dundi_mapping::dcontext, dundi_result::dest, dundi_query_state::directs, dr, dundi_request::dr, dundi_cache_time, DUNDI_CAUSE_GENERAL, DUNDI_COMMAND_PRECACHERP, 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_ies::eids, dundi_query_state::eids, dundi_result::expiration, dundi_ies::expiration, dundi_answer::flags, dundi_result::flags, dundi_hint_metadata::flags, dundi_query_state::fluffy, dundi_ies::hint, dundi_request::hmd, dundi_mapping::list, LOG_NOTICE, LOG_WARNING, dundi_query_state::maps, MAX_RESULTS, dundi_request::maxcount, dundi_mapping::next, dundi_query_state::nocache, NULL, dundi_request::number, dundi_query_state::nummaps, dundi_transaction::parent, dundi_answer::protocol, dundi_request::respcount, 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().

◆ dundi_query()

static int dundi_query ( struct dundi_transaction trans)
static

Definition at line 3503 of file pbx_dundi.c.

3504 {
3505  struct dundi_ie_data ied;
3506  int x;
3507  if (!trans->parent) {
3508  ast_log(LOG_WARNING, "Tried to query a transaction with no parent?!?\n");
3509  return -1;
3510  }
3511  memset(&ied, 0, sizeof(ied));
3513  if (!dundi_eid_zero(&trans->us_eid))
3514  dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid);
3515  for (x=0;x<trans->eidcount;x++)
3516  dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->eids[x]);
3519  dundi_ie_append_short(&ied, DUNDI_IE_TTL, trans->ttl);
3520  if (trans->autokilltimeout)
3521  trans->autokillid = ast_sched_add(sched, trans->autokilltimeout, do_autokill, trans);
3522  return dundi_send(trans, DUNDI_COMMAND_EIDQUERY, 0, 0, &ied);
3523 }
#define DUNDI_COMMAND_EIDQUERY
Definition: dundi.h:162
#define DUNDI_IE_REQEID
Definition: dundi.h:192
dundi_eid query_eid
Definition: pbx_dundi.c:276

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

◆ dundi_query_eid()

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

Retrieve information on a specific EID.

Definition at line 4121 of file pbx_dundi.c.

4122 {
4123  dundi_eid *avoid[1] = { NULL, };
4124  struct dundi_hint_metadata hmd;
4125  memset(&hmd, 0, sizeof(hmd));
4126  return dundi_query_eid_internal(dei, dcontext, &eid, &hmd, dundi_ttl, 0, avoid);
4127 }
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[])
Definition: pbx_dundi.c:4074

References dundi_query_eid_internal(), dundi_ttl, and NULL.

Referenced by dundi_do_query().

◆ dundi_query_eid_internal()

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

4075 {
4076  int res;
4077  struct dundi_request dr;
4078  dundi_eid *rooteid=NULL;
4079  int x;
4080  int ttlms;
4081  int skipped=0;
4082  int foundcache=0;
4083  struct timeval start;
4084 
4085  ttlms = DUNDI_FLUFF_TIME + ttl * DUNDI_TTL_TIME;
4086 
4087  for (x=0;avoid[x];x++)
4088  rooteid = avoid[x];
4089  /* Now perform real check */
4090  memset(&dr, 0, sizeof(dr));
4091  dr.hmd = hmd;
4092  dr.dei = dei;
4093  dr.pfds[0] = dr.pfds[1] = -1;
4094  ast_copy_string(dr.dcontext, dcontext ? dcontext : "e164", sizeof(dr.dcontext));
4095  memcpy(&dr.query_eid, eid, sizeof(dr.query_eid));
4096  if (rooteid)
4097  dr.root_eid = *rooteid;
4098  /* Create transactions */
4099  build_transactions(&dr, ttl, 9999, &foundcache, &skipped, blockempty, 0, 0, NULL, avoid, NULL);
4100 
4101  /* If no TTL, abort and return 0 now after setting TTL expired hint. Couldn't
4102  do this earlier because we didn't know if we were going to have transactions
4103  or not. */
4104  if (!ttl) {
4106  return 0;
4107  }
4108 
4109  /* Optimize transactions */
4110  optimize_transactions(&dr, 9999);
4111  /* Actually perform transactions */
4113  /* Wait for transaction to come back */
4114  start = ast_tvnow();
4115  while (!AST_LIST_EMPTY(&dr.trans) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms))
4116  usleep(1);
4117  res = dr.respcount;
4118  return res;
4119 }
static int query_transactions(struct dundi_request *dr)
Definition: pbx_dundi.c:3571

References ast_copy_string(), AST_LIST_EMPTY, ast_set_flag_nonstd, ast_tvdiff_ms(), ast_tvnow(), build_transactions(), dr, DUNDI_FLUFF_TIME, DUNDI_HINT_TTL_EXPIRED, DUNDI_TTL_TIME, NULL, optimize_transactions(), and query_transactions().

Referenced by dundi_query_eid(), and dundi_query_thread().

◆ dundi_query_read()

static int dundi_query_read ( struct ast_channel chan,
const char *  cmd,
char *  data,