Asterisk - The Open Source Telephony Project GIT-master-3dae2cf
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 (const 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 int outgoing_sip_tech
 
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 char pjsip_outgoing_endpoint [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 4461 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 4135 of file pbx_dundi.c.

4135 {
4136 OPT_BYPASS_CACHE = (1 << 0),
4137};
@ OPT_BYPASS_CACHE
Definition: pbx_dundi.c:4136

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 5282 of file pbx_dundi.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 5282 of file pbx_dundi.c.

◆ abort_request()

static void abort_request ( struct dundi_request dr)
static

Definition at line 3694 of file pbx_dundi.c.

3695{
3696 struct dundi_transaction *trans;
3697
3699 while ((trans = AST_LIST_FIRST(&dr->trans))) {
3700 /* This will remove the transaction from the list */
3701 destroy_trans(trans, 0);
3702 }
3704}
#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:3209
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 2027 of file pbx_dundi.c.

2028{
2029 struct dundi_packet *pack;
2030
2031 /* Ack transmitted packet corresponding to iseqno */
2032 AST_LIST_TRAVERSE(&trans->packets, pack, list) {
2033 if ((pack->h->oseqno + 1) % 255 == iseqno) {
2034 destroy_packet(pack, 0);
2035 if (!AST_LIST_EMPTY(&trans->lasttrans)) {
2036 ast_log(LOG_WARNING, "Whoa, there was still a last trans?\n");
2037 destroy_packets(&trans->lasttrans);
2038 }
2039 AST_LIST_INSERT_HEAD(&trans->lasttrans, pack, list);
2041 return 1;
2042 }
2043 }
2044
2045 return 0;
2046}
#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:2016
static void destroy_packet(struct dundi_packet *pack, int needfree)
Definition: pbx_dundi.c:3200
#define AST_SCHED_DEL(sched, id)
Remove a scheduler entry.
Definition: sched.h:46
unsigned char oseqno
Definition: dundi.h:38
struct dundi_hdr * h
Definition: pbx_dundi.c:225
struct dundi_packet::@411 list
struct dundi_transaction::packetlist packets
struct packetlist lasttrans
Definition: pbx_dundi.c:269
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 4448 of file pbx_dundi.c.

4449{
4450 struct permission *perm;
4451
4452 if (!(perm = ast_calloc(1, sizeof(*perm) + strlen(s) + 1)))
4453 return;
4454
4455 strcpy(perm->name, s);
4456 perm->allow = allow;
4457
4458 AST_LIST_INSERT_TAIL(permlist, perm, list);
4459}
#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::@410 list
char name[0]
Definition: pbx_dundi.c:220

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

3649{
3650 struct dundi_transaction *trans;
3651 int x;
3652 char eid_str[20];
3653 char eid_str2[20];
3654
3655 /* Ignore if not registered */
3656 if (ast_sockaddr_isnull(&p->addr)) {
3657 return 0;
3658 }
3659 if (p->maxms && ((p->lastms < 0) || (p->lastms >= p->maxms)))
3660 return 0;
3661
3662 if (ast_strlen_zero(dr->number))
3663 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);
3664 else
3665 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);
3666
3667 trans = create_transaction(p);
3668 if (!trans)
3669 return -1;
3670 trans->parent = dr;
3671 trans->ttl = ttl;
3672 for (x = 0; avoid[x] && (x < DUNDI_MAX_STACK); x++)
3673 trans->eids[x] = *avoid[x];
3674 trans->eidcount = x;
3675 AST_LIST_INSERT_HEAD(&dr->trans, trans, parentlist);
3676
3677 return 0;
3678}
#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:3143
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
struct ast_sockaddr addr
Definition: pbx_dundi.c:307
int lastms
Definition: pbx_dundi.c:337
dundi_eid eid
Definition: pbx_dundi.c:306
struct dundi_transaction::@413 parentlist
dundi_eid eids[DUNDI_MAX_STACK+1]
Definition: pbx_dundi.c:250
struct dundi_request * parent
Definition: pbx_dundi.c:270
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
Definition: utils.c:2839

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

1302{
1303 if (ast_sockaddr_isnull(&trans->addr)) {
1304 ast_sockaddr_copy(&trans->addr, &p->addr);
1305 }
1306 trans->us_eid = p->us_eid;
1307 trans->them_eid = p->eid;
1308 /* Enable encryption if appropriate */
1309 if (!ast_strlen_zero(p->inkey))
1310 ast_set_flag(trans, FLAG_ENCRYPT);
1311 if (p->maxms) {
1312 trans->autokilltimeout = p->maxms;
1314 if (p->lastms > 1) {
1315 trans->retranstimer = p->lastms * 2;
1316 /* Keep it from being silly */
1317 if (trans->retranstimer < 150)
1318 trans->retranstimer = 150;
1319 }
1322 } else
1324}
#define DUNDI_DEFAULT_RETRANS_TIMER
Definition: dundi.h:217
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:310
char inkey[80]
Definition: pbx_dundi.c:311
struct ast_sockaddr addr
Definition: pbx_dundi.c:248
dundi_eid us_eid
Definition: pbx_dundi.c:252
dundi_eid them_eid
Definition: pbx_dundi.c:253
#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 5282 of file pbx_dundi.c.

◆ avoid_crc32()

static unsigned long avoid_crc32 ( dundi_eid avoid[])
static

Definition at line 3815 of file pbx_dundi.c.

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

References dundi_request::crc32.

Referenced by dundi_lookup_internal().

◆ build_iv()

static void build_iv ( unsigned char *  iv)
static

Definition at line 539 of file pbx_dundi.c.

540{
541 /* XXX Would be nice to be more random XXX */
542 unsigned int *fluffy;
543 int x;
544 fluffy = (unsigned int *)(iv);
545 for (x=0;x<4;x++)
546 fluffy[x] = ast_random();
547}
long int ast_random(void)
Definition: utils.c:2312

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

4464{
4465 char *t, *fields[MAX_OPTS];
4466 struct dundi_mapping *map;
4467 int x;
4468 int y;
4469
4470 t = ast_strdupa(value);
4471
4473 /* Find a double match */
4474 if (!strcasecmp(map->dcontext, name) &&
4475 (!strncasecmp(map->lcontext, value, strlen(map->lcontext)) &&
4476 (!value[strlen(map->lcontext)] ||
4477 (value[strlen(map->lcontext)] == ','))))
4478 break;
4479 }
4480 if (!map) {
4481 if (!(map = ast_calloc(1, sizeof(*map))))
4482 return;
4484 map->dead = 1;
4485 }
4486 map->options = 0;
4487 memset(fields, 0, sizeof(fields));
4488 x = 0;
4489 while (t && x < MAX_OPTS) {
4490 fields[x++] = t;
4491 t = strchr(t, ',');
4492 if (t) {
4493 *t = '\0';
4494 t++;
4495 }
4496 } /* Russell was here, arrrr! */
4497 if ((x == 1) && ast_strlen_zero(fields[0])) {
4498 /* Placeholder mapping */
4499 ast_copy_string(map->dcontext, name, sizeof(map->dcontext));
4500 map->dead = 0;
4501 } else if (x >= 4) {
4502 ast_copy_string(map->dcontext, name, sizeof(map->dcontext));
4503 ast_copy_string(map->lcontext, fields[0], sizeof(map->lcontext));
4504 if ((sscanf(fields[1], "%30d", &map->_weight) == 1) && (map->_weight >= 0) && (map->_weight <= MAX_WEIGHT)) {
4505 ast_copy_string(map->dest, fields[3], sizeof(map->dest));
4506 if ((map->tech = str2tech(fields[2])))
4507 map->dead = 0;
4508 } else if (!strncmp(fields[1], "${", 2) && fields[1][strlen(fields[1]) - 1] == '}') {
4509 map->weightstr = ast_strdup(fields[1]);
4510 ast_copy_string(map->dest, fields[3], sizeof(map->dest));
4511 if ((map->tech = str2tech(fields[2])))
4512 map->dead = 0;
4513 } else {
4514 ast_log(LOG_WARNING, "Invalid weight '%s' specified, deleting entry '%s/%s'\n", fields[1], map->dcontext, map->lcontext);
4515 }
4516 for (y = 4;y < x; y++) {
4517 if (!strcasecmp(fields[y], "nounsolicited"))
4519 else if (!strcasecmp(fields[y], "nocomunsolicit"))
4521 else if (!strcasecmp(fields[y], "residential"))
4523 else if (!strcasecmp(fields[y], "commercial"))
4525 else if (!strcasecmp(fields[y], "mobile"))
4526 map->options |= DUNDI_FLAG_MOBILE;
4527 else if (!strcasecmp(fields[y], "nopartial"))
4529 else
4530 ast_log(LOG_WARNING, "Don't know anything about option '%s'\n", fields[y]);
4531 }
4532 } else
4533 ast_log(LOG_WARNING, "Expected at least %d arguments in map, but got only %d\n", 4, x);
4534}
#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:82
@ DUNDI_FLAG_COMMERCIAL
Definition: dundi.h:80
@ DUNDI_FLAG_NOCOMUNSOLICIT
Definition: dundi.h:86
@ DUNDI_FLAG_RESIDENTIAL
Definition: dundi.h:78
@ DUNDI_FLAG_NOUNSOLICITED
Definition: dundi.h:84
static const char name[]
Definition: format_mp3.c:68
#define DUNDI_FLAG_INTERNAL_NOPARTIAL
Definition: pbx_dundi.c:176
#define MAX_WEIGHT
Definition: pbx_dundi.c:157
#define MAX_OPTS
Definition: pbx_dundi.c:4461
static int str2tech(const char *str)
Definition: pbx_dundi.c:400
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
char lcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:295
char * weightstr
Definition: pbx_dundi.c:297
struct dundi_mapping::@417 list
char dest[512]
Definition: pbx_dundi.c:301
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:294
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 4634 of file pbx_dundi.c.

4635{
4636 struct dundi_peer *peer;
4637 dundi_eid testeid;
4638 int needregister=0;
4639 char eid_str[20];
4640 int port = 0;
4641
4643 AST_LIST_TRAVERSE(&peers, peer, list) {
4644 if (!ast_eid_cmp(&peer->eid, eid)) {
4645 break;
4646 }
4647 }
4648 if (!peer) {
4649 /* Add us into the list */
4650 if (!(peer = ast_calloc(1, sizeof(*peer)))) {
4652 return;
4653 }
4654 peer->registerid = -1;
4655 peer->registerexpire = -1;
4656 peer->qualifyid = -1;
4657 populate_addr(peer, eid);
4659 }
4660 peer->dead = 0;
4661 peer->eid = *eid;
4662 peer->us_eid = global_eid;
4666 for (; v; v = v->next) {
4667 if (!strcasecmp(v->name, "inkey")) {
4668 ast_copy_string(peer->inkey, v->value, sizeof(peer->inkey));
4669 } else if (!strcasecmp(v->name, "outkey")) {
4670 ast_copy_string(peer->outkey, v->value, sizeof(peer->outkey));
4671 } else if (!strcasecmp(v->name, "port")) {
4672 port = atoi(v->value);
4673 } else if (!strcasecmp(v->name, "host")) {
4674 if (!strcasecmp(v->value, "dynamic")) {
4675 peer->dynamic = 1;
4676 } else {
4677 struct ast_sockaddr *addrs;
4678
4679 if (ast_sockaddr_resolve(&addrs, v->value, PARSE_PORT_FORBID, AF_UNSPEC) > 0) {
4680 ast_sockaddr_copy(&peer->addr, &addrs[0]);
4681 peer->dynamic = 0;
4682 ast_free(addrs);
4683 } else {
4684 ast_log(LOG_WARNING, "Unable to find host '%s' at line %d\n", v->value, v->lineno);
4685 peer->dead = 1;
4686 }
4687 }
4688 } else if (!strcasecmp(v->name, "ustothem")) {
4689 if (!ast_str_to_eid(&testeid, v->value))
4690 peer->us_eid = testeid;
4691 else
4692 ast_log(LOG_WARNING, "'%s' is not a valid DUNDi Entity Identifier at line %d\n", v->value, v->lineno);
4693 } else if (!strcasecmp(v->name, "include")) {
4694 append_permission(&peer->include, v->value, 1);
4695 } else if (!strcasecmp(v->name, "permit")) {
4696 append_permission(&peer->permit, v->value, 1);
4697 } else if (!strcasecmp(v->name, "noinclude")) {
4698 append_permission(&peer->include, v->value, 0);
4699 } else if (!strcasecmp(v->name, "deny")) {
4700 append_permission(&peer->permit, v->value, 0);
4701 } else if (!strcasecmp(v->name, "register")) {
4702 needregister = ast_true(v->value);
4703 } else if (!strcasecmp(v->name, "order")) {
4704 if (!strcasecmp(v->value, "primary"))
4705 peer->order = 0;
4706 else if (!strcasecmp(v->value, "secondary"))
4707 peer->order = 1;
4708 else if (!strcasecmp(v->value, "tertiary"))
4709 peer->order = 2;
4710 else if (!strcasecmp(v->value, "quartiary"))
4711 peer->order = 3;
4712 else {
4713 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);
4714 }
4715 } else if (!strcasecmp(v->name, "qualify")) {
4716 if (!strcasecmp(v->value, "no")) {
4717 peer->maxms = 0;
4718 } else if (!strcasecmp(v->value, "yes")) {
4719 peer->maxms = DEFAULT_MAXMS;
4720 } else if (sscanf(v->value, "%30d", &peer->maxms) != 1) {
4721 ast_log(LOG_WARNING, "Qualification of peer '%s' should be 'yes', 'no', or a number of milliseconds at line %d of dundi.conf\n",
4722 ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), v->lineno);
4723 peer->maxms = 0;
4724 }
4725 } else if (!strcasecmp(v->name, "model")) {
4726 if (!strcasecmp(v->value, "inbound"))
4727 peer->model = DUNDI_MODEL_INBOUND;
4728 else if (!strcasecmp(v->value, "outbound"))
4730 else if (!strcasecmp(v->value, "symmetric"))
4732 else if (!strcasecmp(v->value, "none"))
4733 peer->model = 0;
4734 else {
4735 ast_log(LOG_WARNING, "Unknown model '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n",
4736 v->value, v->lineno);
4737 }
4738 } else if (!strcasecmp(v->name, "precache")) {
4739 if (!strcasecmp(v->value, "inbound"))
4741 else if (!strcasecmp(v->value, "outbound"))
4743 else if (!strcasecmp(v->value, "symmetric"))
4745 else if (!strcasecmp(v->value, "none"))
4746 peer->pcmodel = 0;
4747 else {
4748 ast_log(LOG_WARNING, "Unknown pcmodel '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n",
4749 v->value, v->lineno);
4750 }
4751 }
4752 }
4753
4754 if (!ast_sockaddr_isnull(&peer->addr)) {
4755 ast_sockaddr_set_port(&peer->addr, (0 < port) ? port : DUNDI_PORT);
4756 }
4757
4758 (*globalpcmode) |= peer->pcmodel;
4759 if (!peer->model && !peer->pcmodel) {
4760 ast_log(LOG_WARNING, "Peer '%s' lacks a model or pcmodel, discarding!\n",
4761 ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
4762 peer->dead = 1;
4763 } else if ((peer->model & DUNDI_MODEL_INBOUND) && (peer->pcmodel & DUNDI_MODEL_OUTBOUND)) {
4764 ast_log(LOG_WARNING, "Peer '%s' may not be both inbound/symmetric model and outbound/symmetric precache model, discarding!\n",
4765 ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
4766 peer->dead = 1;
4767 } else if ((peer->model & DUNDI_MODEL_OUTBOUND) && (peer->pcmodel & DUNDI_MODEL_INBOUND)) {
4768 ast_log(LOG_WARNING, "Peer '%s' may not be both outbound/symmetric model and inbound/symmetric precache model, discarding!\n",
4769 ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
4770 peer->dead = 1;
4771 } else if (!AST_LIST_EMPTY(&peer->include) && !(peer->model & DUNDI_MODEL_OUTBOUND) && !(peer->pcmodel & DUNDI_MODEL_INBOUND)) {
4772 ast_log(LOG_WARNING, "Peer '%s' is supposed to be included in outbound searches but isn't an outbound peer or inbound precache!\n",
4773 ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
4774 } else if (!AST_LIST_EMPTY(&peer->permit) && !(peer->model & DUNDI_MODEL_INBOUND) && !(peer->pcmodel & DUNDI_MODEL_OUTBOUND)) {
4775 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",
4776 ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
4777 } else {
4778 if (ast_eid_cmp(&peer->eid, &empty_eid)) {
4779 /* Schedule any items for explicitly configured peers. */
4780 if (needregister) {
4781 peer->registerid = ast_sched_add(sched, 2000, do_register, peer);
4782 }
4783 qualify_peer(peer, 1);
4784 }
4785 }
4787}
#define ast_free(a)
Definition: astmm.h:180
#define DEFAULT_MAXMS
Definition: chan_iax2.c:394
#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:214
#define DUNDI_MODEL_INBOUND
Definition: pbx_dundi.c:159
static void populate_addr(struct dundi_peer *peer, dundi_eid *eid)
Definition: pbx_dundi.c:4594
static void append_permission(struct permissionlist *permlist, const char *s, int allow)
Definition: pbx_dundi.c:4448
static void destroy_permissions(struct permissionlist *permlist)
Definition: pbx_dundi.c:4380
static void qualify_peer(struct dundi_peer *peer, int schedonly)
Definition: pbx_dundi.c:4571
#define DUNDI_MODEL_OUTBOUND
Definition: pbx_dundi.c:160
static int do_register(const void *data)
Definition: pbx_dundi.c:4537
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: utils.c:2199
Socket address structure.
Definition: netsock2.h:97
struct ast_variable * next
char outkey[80]
Definition: pbx_dundi.c:312
unsigned int dynamic
Definition: pbx_dundi.c:336
struct dundi_peer::permissionlist permit
int qualifyid
Definition: pbx_dundi.c:315
struct dundi_peer::@418 list
int registerid
Definition: pbx_dundi.c:314
int pcmodel
Definition: pbx_dundi.c:334
struct permissionlist include
Definition: pbx_dundi.c:309
int registerexpire
Definition: pbx_dundi.c:327
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
Definition: utils.c:3094
int ast_str_to_eid(struct ast_eid *eid, const char *s)
Convert a string into an EID.
Definition: utils.c:3077

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

2117{
2118 unsigned char tmp[16];
2119 char *s;
2120 build_iv(tmp);
2121 secret[0] = '\0';
2122 ast_base64encode(secret, tmp, sizeof(tmp), seclen);
2123 /* Eliminate potential bad characters */
2124 while((s = strchr(secret, ';'))) *s = '+';
2125 while((s = strchr(secret, '/'))) *s = '+';
2126 while((s = strchr(secret, ':'))) *s = '+';
2127 while((s = strchr(secret, '@'))) *s = '+';
2128}
static int tmp()
Definition: bt_open.c:389
static void build_iv(unsigned char *iv)
Definition: pbx_dundi.c:539
int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
Encode data in base64.
Definition: 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 3706 of file pbx_dundi.c.

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

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

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

1177{
1178 char data[1024];
1179 char *ptr, *term, *src;
1180 int tech;
1181 struct ast_flags flags;
1182 int weight;
1183 int length;
1184 int z;
1185 char fs[256];
1186
1187 /* Build request string */
1188 if (!ast_db_get("dundi/cache", key, data, sizeof(data))) {
1189 time_t timeout;
1190 ptr = data;
1191 if (!ast_get_time_t(ptr, &timeout, 0, &length)) {
1192 int expiration = timeout - now;
1193 if (expiration > 0) {
1194 ast_debug(1, "Found cache expiring in %d seconds!\n", expiration);
1195 ptr += length + 1;
1196 while((sscanf(ptr, "%30d/%30d/%30d/%n", (int *)&(flags.flags), &weight, &tech, &length) == 3)) {
1197 ptr += length;
1198 term = strchr(ptr, '|');
1199 if (term) {
1200 *term = '\0';
1201 src = strrchr(ptr, '/');
1202 if (src) {
1203 *src = '\0';
1204 src++;
1205 } else
1206 src = "";
1207 ast_debug(1, "Found cached answer '%s/%s' originally from '%s' with flags '%s' on behalf of '%s'\n",
1208 tech2str(tech), ptr, src, dundi_flags2str(fs, sizeof(fs), flags.flags), eid_str_full);
1209 /* Make sure it's not already there */
1210 for (z=0;z<req->respcount;z++) {
1211 if ((req->dr[z].techint == tech) &&
1212 !strcmp(req->dr[z].dest, ptr))
1213 break;
1214 }
1215 if (z == req->respcount) {
1216 /* Copy into parent responses */
1217 ast_copy_flags(&(req->dr[req->respcount]), &flags, AST_FLAGS_ALL);
1218 req->dr[req->respcount].weight = weight;
1219 req->dr[req->respcount].techint = tech;
1220 req->dr[req->respcount].expiration = expiration;
1221 dundi_str_short_to_eid(&req->dr[req->respcount].eid, src);
1223 sizeof(req->dr[req->respcount].eid_str), &req->dr[req->respcount].eid);
1224 ast_copy_string(req->dr[req->respcount].dest, ptr,
1225 sizeof(req->dr[req->respcount].dest));
1226 ast_copy_string(req->dr[req->respcount].tech, tech2str(tech),
1227 sizeof(req->dr[req->respcount].tech));
1228 req->respcount++;
1230 } else if (req->dr[z].weight > weight)
1231 req->dr[z].weight = weight;
1232 ptr = term + 1;
1233 }
1234 }
1235 /* We found *something* cached */
1236 if (expiration < *lowexpiration)
1237 *lowexpiration = expiration;
1238 return 1;
1239 } else
1240 ast_db_del("dundi/cache", key);
1241 } else
1242 ast_db_del("dundi/cache", key);
1243 }
1244
1245 return 0;
1246}
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:427
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: main/db.c:478
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:248
@ DUNDI_HINT_DONT_ASK
Definition: dundi.h:94
static char * tech2str(int tech)
Definition: pbx_dundi.c:382
int ast_get_time_t(const char *src, time_t *dst, time_t _default, int *consumed)
Parse a time (integer) string.
Definition: utils.c:2446
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:280
char dest[256]
Definition: dundi.h:235
char eid_str[20]
Definition: dundi.h:233
int techint
Definition: dundi.h:231
char tech[10]
Definition: dundi.h:234
int weight
Definition: dundi.h:229
int expiration
Definition: dundi.h:230
dundi_eid eid
Definition: dundi.h:232
#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 905 of file pbx_dundi.c.

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

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

871{
872 int unaffected;
873 char key1[256];
874 char key2[256];
875 char eidpeer_str[20];
876 char eidroot_str[20];
877 char data[80];
878 time_t timeout;
879
880 if (expiration < 0)
881 expiration = dundi_cache_time;
882
883 /* Only cache hint if "don't ask" is there... */
884 if (!ast_test_flag_nonstd(hint, htons(DUNDI_HINT_DONT_ASK)))
885 return 0;
886
887 unaffected = ast_test_flag_nonstd(hint, htons(DUNDI_HINT_UNAFFECTED));
888
889 dundi_eid_to_str_short(eidpeer_str, sizeof(eidpeer_str), eidpeer);
890 dundi_eid_to_str_short(eidroot_str, sizeof(eidroot_str), &req->root_eid);
891 snprintf(key1, sizeof(key1), "hint/%s/%s/%s/e%08x", eidpeer_str, hint->data, req->dcontext, unaffected ? 0 : req->crc32);
892 snprintf(key2, sizeof(key2), "hint/%s/%s/%s/r%s", eidpeer_str, hint->data, req->dcontext, eidroot_str);
893
894 time(&timeout);
895 timeout += expiration;
896 snprintf(data, sizeof(data), "%ld|", (long)(timeout));
897
898 ast_db_put("dundi/cache", key1, data);
899 ast_debug(1, "Caching hint at '%s'\n", key1);
900 ast_db_put("dundi/cache", key2, data);
901 ast_debug(1, "Caching hint at '%s'\n", key2);
902 return 0;
903}
unsigned char data[0]
Definition: dundi.h:114
#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 3680 of file pbx_dundi.c.

3681{
3682 struct dundi_transaction *trans;
3683
3685 while ((trans = AST_LIST_REMOVE_HEAD(&dr->trans, parentlist))) {
3686 /* Orphan transaction from request */
3687 trans->parent = NULL;
3688 /* Send final cancel */
3689 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
3690 }
3692}
#define DUNDI_COMMAND_CANCEL
Definition: dundi.h:173
#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:3314
#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 1498 of file pbx_dundi.c.

1499{
1500 unsigned char dst[128];
1501 int res;
1502 struct ast_key *key, *skey;
1503 char eid_str[20];
1504 ast_debug(1, "Expected '%08x' got '%08x'\n", peer->them_keycrc32, keycrc32);
1505 if (peer->them_keycrc32 && (peer->them_keycrc32 == keycrc32)) {
1506 /* A match */
1507 return 1;
1508 } else if (!newkey || !newsig)
1509 return 0;
1510 if (!memcmp(peer->rxenckey, newkey, 128) &&
1511 !memcmp(peer->rxenckey + 128, newsig, 128)) {
1512 /* By definition, a match */
1513 return 1;
1514 }
1515 /* Decrypt key */
1516 key = ast_key_get(peer->outkey, AST_KEY_PRIVATE);
1517 if (!key) {
1518 ast_log(LOG_NOTICE, "Unable to find key '%s' to decode shared key from '%s'\n",
1519 peer->outkey, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
1520 return -1;
1521 }
1522
1523 skey = ast_key_get(peer->inkey, AST_KEY_PUBLIC);
1524 if (!skey) {
1525 ast_log(LOG_NOTICE, "Unable to find key '%s' to verify shared key from '%s'\n",
1526 peer->inkey, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
1527 return -1;
1528 }
1529
1530 /* First check signature */
1531 res = ast_check_signature_bin(skey, (char *)newkey, 128, newsig);
1532 if (res)
1533 return 0;
1534
1535 res = ast_decrypt_bin(dst, newkey, sizeof(dst), key);
1536 if (res != 16) {
1537 if (res >= 0)
1538 ast_log(LOG_NOTICE, "Weird, key decoded to the wrong size (%d)\n", res);
1539 return 0;
1540 }
1541 /* Decrypted, passes signature */
1542 ast_debug(1, "Wow, new key combo passed signature and decrypt!\n");
1543 memcpy(peer->rxenckey, newkey, 128);
1544 memcpy(peer->rxenckey + 128, newsig, 128);
1545 peer->them_keycrc32 = crc32(0L, peer->rxenckey, 128);
1546 ast_aes_set_decrypt_key(dst, &peer->them_dcx);
1547 ast_aes_set_encrypt_key(dst, &peer->them_ecx);
1548 return 1;
1549}
int ast_aes_set_encrypt_key(const unsigned char *key, ast_aes_encrypt_key *ctx)
Set an encryption key.
Definition: res_crypto.c:700
struct ast_key * ast_key_get(const char *kname, int ktype)
Retrieve a key.
Definition: res_crypto.c:149
#define AST_KEY_PUBLIC
Definition: crypto.h:46
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:634
#define AST_KEY_PRIVATE
Definition: crypto.h:47
int ast_aes_set_decrypt_key(const unsigned char *key, ast_aes_decrypt_key *ctx)
Set a decryption key.
Definition: res_crypto.c:709
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:472
#define LOG_NOTICE
uint32_t them_keycrc32
Definition: pbx_dundi.c:323
unsigned char rxenckey[256]
Definition: pbx_dundi.c:319
ast_aes_decrypt_key them_dcx
Definition: pbx_dundi.c:325
ast_aes_encrypt_key them_ecx
Definition: pbx_dundi.c:324

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

2184{
2185 char oldsecret[80];
2186 time_t now;
2187
2188 time(&now);
2189#if 0
2190 printf("%ld/%ld\n", now, rotatetime);
2191#endif
2192 if ((now - rotatetime) >= 0) {
2193 /* Time to rotate keys */
2194 ast_copy_string(oldsecret, cursecret, sizeof(oldsecret));
2196 save_secret(cursecret, oldsecret);
2197 }
2198}
static void build_secret(char *secret, int seclen)
Definition: pbx_dundi.c:2116
static void save_secret(const char *newkey, const char *oldkey)
Definition: pbx_dundi.c:2131
static char cursecret[80]
Definition: pbx_dundi.c:209
static time_t rotatetime
Definition: pbx_dundi.c:213

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

3802{
3803 struct dundi_request *cur;
3804
3807 if (cur == dr)
3808 break;
3809 }
3811
3812 return cur ? 1 : 0;
3813}
struct dundi_request::@416 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 2423 of file pbx_dundi.c.

2424{
2425 int which=0, len;
2426 char *ret = NULL;
2427 struct dundi_peer *p;
2428 char eid_str[20];
2429
2430 if (pos != rpos)
2431 return NULL;
2433 len = strlen(word);
2435 const char *s = ast_eid_to_str(eid_str, sizeof(eid_str), &p->eid);
2436 if (!strncasecmp(word, s, len) && ++which > state) {
2437 ret = ast_strdup(s);
2438 break;
2439 }
2440 }
2442 return ret;
2443}
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 3143 of file pbx_dundi.c.

3144{
3145 struct dundi_transaction *trans;
3146 int tid;
3147
3148 /* Don't allow creation of transactions to non-registered peers */
3149 if (p && ast_sockaddr_isnull(&p->addr)) {
3150 return NULL;
3151 }
3152 tid = get_trans_id();
3153 if (tid < 1)
3154 return NULL;
3155 if (!(trans = ast_calloc(1, sizeof(*trans))))
3156 return NULL;
3157
3158 if (global_storehistory) {
3159 trans->start = ast_tvnow();
3161 }
3163 trans->autokillid = -1;
3164 if (p) {
3165 apply_peer(trans, p);
3166 if (!p->sentfullkey)
3168 }
3169 trans->strans = tid;
3171
3172 return trans;
3173}
static void apply_peer(struct dundi_transaction *trans, struct dundi_peer *p)
Definition: pbx_dundi.c:1301
static int get_trans_id(void)
Definition: pbx_dundi.c:486
static int global_storehistory
Definition: pbx_dundi.c:200
int sentfullkey
Definition: pbx_dundi.c:316
unsigned short strans
Definition: pbx_dundi.c:262
struct dundi_transaction::@414 all
struct timeval start
Definition: pbx_dundi.c:249
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159

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

1396{
1397 unsigned char lastblock[16];
1398 int x;
1399 memcpy(lastblock, iv, sizeof(lastblock));
1400 while(len > 0) {
1401 ast_aes_decrypt(src, dst, dcx);
1402 for (x=0;x<16;x++)
1403 dst[x] ^= lastblock[x];
1404 memcpy(lastblock, src, sizeof(lastblock));
1405 dst += 16;
1406 src += 16;
1407 len -= 16;
1408 }
1409 return 0;
1410}
int ast_aes_decrypt(const unsigned char *in, unsigned char *out, const ast_aes_decrypt_key *key)
AES decrypt data.
Definition: res_crypto.c:790

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

1552{
1553 struct permission *cur, *perm;
1554
1555 *peer_dst = *peer_src;
1556 AST_LIST_NEXT(peer_dst, list) = NULL;
1557
1558 /* Scheduled items cannot go with the copy */
1559 peer_dst->registerid = -1;
1560 peer_dst->qualifyid = -1;
1561 peer_dst->registerexpire = -1;
1562
1563 /* Transactions and lookup history cannot go with the copy either */
1564 peer_dst->regtrans = NULL;
1565 peer_dst->qualtrans = NULL;
1566 memset(&peer_dst->lookups, 0, sizeof(peer_dst->lookups));
1567
1568 memset(&peer_dst->permit, 0, sizeof(peer_dst->permit));
1569 memset(&peer_dst->include, 0, sizeof(peer_dst->permit));
1570
1571 AST_LIST_TRAVERSE(&peer_src->permit, cur, list) {
1572 if (!(perm = ast_calloc(1, sizeof(*perm) + strlen(cur->name) + 1)))
1573 continue;
1574
1575 perm->allow = cur->allow;
1576 strcpy(perm->name, cur->name);
1577
1578 AST_LIST_INSERT_HEAD(&peer_dst->permit, perm, list);
1579 }
1580
1581 AST_LIST_TRAVERSE(&peer_src->include, cur, list) {
1582 if (!(perm = ast_calloc(1, sizeof(*perm) + strlen(cur->name) + 1)))
1583 continue;
1584
1585 perm->allow = cur->allow;
1586 strcpy(perm->name, cur->name);
1587
1588 AST_LIST_INSERT_HEAD(&peer_dst->include, perm, list);
1589 }
1590}
#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:329
struct dundi_transaction * regtrans
Definition: pbx_dundi.c:331
struct dundi_transaction * qualtrans
Definition: pbx_dundi.c:332

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

4413{
4414 ast_free(map->weightstr);
4415 ast_free(map);
4416}

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

3201{
3202 if (pack->parent)
3203 AST_LIST_REMOVE(&pack->parent->packets, pack, list);
3205 if (needfree)
3206 ast_free(pack);
3207}
#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:227

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

2017{
2018 struct dundi_packet *pack;
2019
2020 while ((pack = AST_LIST_REMOVE_HEAD(p, list))) {
2022 ast_free(pack);
2023 }
2024}

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

4389{
4390 int idx;
4391
4394 if (peer->regtrans) {
4395 destroy_trans(peer->regtrans, 0);
4396 }
4398 if (peer->qualtrans) {
4399 destroy_trans(peer->qualtrans, 0);
4400 }
4403
4404 /* Release lookup history */
4405 for (idx = 0; idx < ARRAY_LEN(peer->lookups); ++idx) {
4406 ast_free(peer->lookups[idx]);
4407 }
4408
4409 ast_free(peer);
4410}
#define ARRAY_LEN(a)
Definition: utils.h:666

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

4381{
4382 struct permission *perm;
4383
4384 while ((perm = AST_LIST_REMOVE_HEAD(permlist, list)))
4385 ast_free(perm);
4386}

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

3210{
3211 struct dundi_peer *peer;
3212 int ms;
3213 int x;
3214 int cnt;
3215 char eid_str[20];
3217 AST_LIST_TRAVERSE(&peers, peer, list) {
3218 if (peer->regtrans == trans)
3219 peer->regtrans = NULL;
3220 if (peer->qualtrans == trans) {
3221 if (fromtimeout) {
3222 if (peer->lastms > -1)
3223 ast_log(LOG_NOTICE, "Peer '%s' has become UNREACHABLE!\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
3224 peer->lastms = -1;
3225 } else {
3226 ms = ast_tvdiff_ms(ast_tvnow(), peer->qualtx);
3227 if (ms < 1)
3228 ms = 1;
3229 if (ms < peer->maxms) {
3230 if ((peer->lastms >= peer->maxms) || (peer->lastms < 0))
3231 ast_log(LOG_NOTICE, "Peer '%s' has become REACHABLE!\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
3232 } else if (peer->lastms < peer->maxms) {
3233 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);
3234 }
3235 peer->lastms = ms;
3236 }
3237 peer->qualtrans = NULL;
3238 }
3239 if (ast_test_flag(trans, FLAG_STOREHIST)) {
3240 if (trans->parent && !ast_strlen_zero(trans->parent->number)) {
3241 if (!ast_eid_cmp(&trans->them_eid, &peer->eid)) {
3242 peer->avgms = 0;
3243 cnt = 0;
3245 for (x=DUNDI_TIMING_HISTORY-1;x>0;x--) {
3246 peer->lookuptimes[x] = peer->lookuptimes[x-1];
3247 peer->lookups[x] = peer->lookups[x-1];
3248 if (peer->lookups[x]) {
3249 peer->avgms += peer->lookuptimes[x];
3250 cnt++;
3251 }
3252 }
3253 peer->lookuptimes[0] = ast_tvdiff_ms(ast_tvnow(), trans->start);
3254 peer->lookups[0] = ast_malloc(strlen(trans->parent->number) + strlen(trans->parent->dcontext) + 2);
3255 if (peer->lookups[0]) {
3256 sprintf(peer->lookups[0], "%s@%s", trans->parent->number, trans->parent->dcontext);
3257 peer->avgms += peer->lookuptimes[0];
3258 cnt++;
3259 }
3260 if (cnt)
3261 peer->avgms /= cnt;
3262 }
3263 }
3264 }
3265 }
3266 }
3267 if (trans->parent) {
3268 /* Unlink from parent if appropriate */
3269 AST_LIST_REMOVE(&trans->parent->trans, trans, parentlist);
3270 if (AST_LIST_EMPTY(&trans->parent->trans)) {
3271 /* Wake up sleeper */
3272 if (trans->parent->pfds[1] > -1) {
3273 if (write(trans->parent->pfds[1], "killa!", 6) < 0) {
3274 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
3275 }
3276 }
3277 }
3278 }
3279 /* Unlink from all trans */
3280 AST_LIST_REMOVE(&alltrans, trans, all);
3281 destroy_packets(&trans->packets);
3282 destroy_packets(&trans->lasttrans);
3284 if (trans->thread) {
3285 /* If used by a thread, mark as dead and be done */
3286 ast_set_flag(trans, FLAG_DEAD);
3287 } else
3288 ast_free(trans);
3289}
#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:328
struct timeval qualtx
Definition: pbx_dundi.c:339
int pfds[2]
Definition: pbx_dundi.c:287
struct dundi_request::@415 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:107
#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 3531 of file pbx_dundi.c.

3532{
3533 struct dundi_transaction *trans;
3535 AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) {
3536 dundi_discover(trans);
3537 }
3539 return 0;
3540}
static int dundi_discover(struct dundi_transaction *trans)
Definition: pbx_dundi.c:3419

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

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

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

4564{
4565 struct dundi_peer *peer = (struct dundi_peer *)data;
4566 peer->qualifyid = -1;
4567 qualify_peer(peer, 0);
4568 return 0;
4569}

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

4538{
4539 struct dundi_ie_data ied;
4540 struct dundi_peer *peer = (struct dundi_peer *)data;
4541 char eid_str[20];
4542 char eid_str2[20];
4543 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));
4545 /* Destroy old transaction if there is one */
4546 if (peer->regtrans)
4547 destroy_trans(peer->regtrans, 0);
4548 peer->regtrans = create_transaction(peer);
4549 if (peer->regtrans) {
4551 memset(&ied, 0, sizeof(ied));
4555 dundi_send(peer->regtrans, DUNDI_COMMAND_REGREQ, 0, 0, &ied);
4556
4557 } else
4558 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));
4559
4560 return 0;
4561}
int dundi_ie_append_eid(struct dundi_ie_data *ied, unsigned char ie, dundi_eid *eid)
Definition: dundi-parser.c:612
int dundi_ie_append_short(struct dundi_ie_data *ied, unsigned char ie, unsigned short value)
Definition: dundi-parser.c:600
#define DUNDI_IE_VERSION
Definition: dundi.h:190
#define DUNDI_DEFAULT_VERSION
Definition: dundi.h:219
#define DUNDI_IE_EXPIRATION
Definition: dundi.h:191
#define DUNDI_IE_EID
Definition: dundi.h:184
#define DUNDI_COMMAND_REGREQ
Definition: dundi.h:171
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(), do_register(), 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(), and do_register().

◆ do_register_expire()

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

Definition at line 1327 of file pbx_dundi.c.

1328{
1329 struct dundi_peer *peer = (struct dundi_peer *)data;
1330 char eid_str[20];
1331
1332 ast_debug(1, "Register expired for '%s'\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
1333 ast_db_del("dundi/dpeers", dundi_eid_to_str_short(eid_str, sizeof(eid_str), &peer->eid));
1334 peer->registerexpire = -1;
1335 peer->lastms = 0;
1336 ast_sockaddr_setnull(&peer->addr);
1337 return 0;
1338}
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 4205 of file pbx_dundi.c.

4206{
4207 ast_free(drds);
4208}

References ast_free.

Referenced by drds_destroy_cb(), and dundi_query_read().

◆ drds_destroy_cb()

static void drds_destroy_cb ( void *  data)
static

Definition at line 4210 of file pbx_dundi.c.

4211{
4212 struct dundi_result_datastore *drds = data;
4213 drds_destroy(drds);
4214}
static void drds_destroy(struct dundi_result_datastore *drds)
Definition: pbx_dundi.c:4205

References drds_destroy().

◆ dundi_ack()

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

Definition at line 457 of file pbx_dundi.c.

458{
459 return dundi_send(trans, DUNDI_COMMAND_ACK, 0, final, NULL);
460}
#define DUNDI_COMMAND_ACK
Definition: dundi.h:161

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

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

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

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

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

4814{
4815 return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_CANMATCH);
4816}
static int priority
@ DUNDI_FLAG_CANMATCH
Definition: dundi.h:74
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:4789

References voicemailpwcheck::context, DUNDI_FLAG_CANMATCH, dundi_helper(), and priority.

◆ dundi_debug_output()

static void dundi_debug_output ( const char *  data)
static

Definition at line 358 of file pbx_dundi.c.

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

References ast_verbose(), and dundidebug.

Referenced by load_module().

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

1413{
1414 int space = *dstlen;
1415 unsigned long bytes;
1416 struct dundi_hdr *h;
1417 unsigned char *decrypt_space;
1418 decrypt_space = ast_alloca(srclen);
1419 decrypt_memcpy(decrypt_space, src->encdata, srclen, src->iv, &trans->dcx);
1420 /* Setup header */
1421 h = (struct dundi_hdr *)dst;
1422 *h = *ohdr;
1423 bytes = space - 6;
1424 if (uncompress(dst + 6, &bytes, decrypt_space, srclen) != Z_OK) {
1425 ast_debug(1, "Ouch, uncompress failed :(\n");
1426 return NULL;
1427 }
1428 /* Update length */
1429 *dstlen = bytes + 6;
1430 /* Return new header */
1431 return h;
1432}
#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:1395
unsigned char iv[16]
Definition: dundi.h:100
unsigned char encdata[0]
Definition: dundi.h:101
ast_aes_decrypt_key dcx
Definition: pbx_dundi.c:255

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

3420{
3421 struct dundi_ie_data ied;
3422 int x;
3423 if (!trans->parent) {
3424 ast_log(LOG_WARNING, "Tried to discover a transaction with no parent?!?\n");
3425 return -1;
3426 }
3427 memset(&ied, 0, sizeof(ied));
3429 if (!dundi_eid_zero(&trans->us_eid))
3431 for (x=0;x<trans->eidcount;x++)
3432 dundi_ie_append_eid_appropriately(&ied, trans->parent->dcontext, &trans->eids[x], &trans->us_eid);
3435 dundi_ie_append_short(&ied, DUNDI_IE_TTL, trans->ttl);
3436 if (trans->parent->cbypass)
3438 if (trans->autokilltimeout)
3439 trans->autokillid = ast_sched_add(sched, trans->autokilltimeout, do_autokill, trans);
3440 return dundi_send(trans, DUNDI_COMMAND_DPDISCOVER, 0, 0, &ied);
3441}
int dundi_ie_append(struct dundi_ie_data *ied, unsigned char ie)
Definition: dundi-parser.c:622
int dundi_ie_append_str(struct dundi_ie_data *ied, unsigned char ie, char *str)
Definition: dundi-parser.c:607
#define DUNDI_IE_CACHEBYPASS
Definition: dundi.h:209
#define DUNDI_IE_TTL
Definition: dundi.h:189
#define DUNDI_IE_CALLED_CONTEXT
Definition: dundi.h:185
#define DUNDI_IE_CALLED_NUMBER
Definition: dundi.h:186
#define DUNDI_IE_EID_DIRECT
Definition: dundi.h:187
#define DUNDI_COMMAND_DPDISCOVER
Definition: dundi.h:162
static void dundi_ie_append_eid_appropriately(struct dundi_ie_data *ied, char *context, dundi_eid *eid, dundi_eid *us)
Definition: pbx_dundi.c:3397
static int do_autokill(const void *data)
Definition: pbx_dundi.c:3386

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

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

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

References a, ast_cli(), ast_copy_string(), ast_tvdiff_ms(), ast_tvnow(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, voicemailpwcheck::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 2556 of file pbx_dundi.c.

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

References a, ast_cli(), ast_copy_string(), ast_str_to_eid(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, voicemailpwcheck::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 1434 of file pbx_dundi.c.

1435{
1436 unsigned char *compress_space;
1437 int len;
1438 int res;
1439 unsigned long bytes;
1440 struct dundi_ie_data ied;
1441 struct dundi_peer *peer;
1442 unsigned char iv[16];
1443 len = pack->datalen + pack->datalen / 100 + 42;
1444 compress_space = ast_alloca(len);
1445 memset(compress_space, 0, len);
1446 /* We care about everthing save the first 6 bytes of header */
1447 bytes = len;
1448 res = compress(compress_space, &bytes, pack->data + 6, pack->datalen - 6);
1449 if (res != Z_OK) {
1450 ast_debug(1, "Ouch, compression failed!\n");
1451 return -1;
1452 }
1453 memset(&ied, 0, sizeof(ied));
1454 /* Say who we are */
1455 if (!pack->h->iseqno && !pack->h->oseqno) {
1456 /* Need the key in the first copy */
1457 if (!(peer = find_peer(&trans->them_eid)))
1458 return -1;
1459 if (update_key(peer))
1460 return -1;
1461 if (!peer->sentfullkey)
1463 /* Append key data */
1464 dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid);
1465 if (ast_test_flag(trans, FLAG_SENDFULLKEY)) {
1467 dundi_ie_append_raw(&ied, DUNDI_IE_SIGNATURE, peer->txenckey + 128, 128);
1468 } else {
1470 }
1471 /* Setup contexts */
1472 trans->ecx = peer->us_ecx;
1473 trans->dcx = peer->us_dcx;
1474
1475 /* We've sent the full key */
1476 peer->sentfullkey = 1;
1477 }
1478 /* Build initialization vector */
1479 build_iv(iv);
1480 /* Add the field, rounded up to 16 bytes */
1481 dundi_ie_append_encdata(&ied, DUNDI_IE_ENCDATA, iv, NULL, ((bytes + 15) / 16) * 16);
1482 /* Copy the data */
1483 if ((ied.pos + bytes) >= sizeof(ied.buf)) {
1484 ast_log(LOG_NOTICE, "Final packet too large!\n");
1485 return -1;
1486 }
1487 encrypt_memcpy(ied.buf + ied.pos, compress_space, bytes, iv, &trans->ecx);
1488 ied.pos += ((bytes + 15) / 16) * 16;
1489 /* Reconstruct header */
1490 pack->datalen = sizeof(struct dundi_hdr);
1492 pack->h->cmdflags = 0;
1493 memcpy(pack->h->ies, ied.buf, ied.pos);
1494 pack->datalen += ied.pos;
1495 return 0;
1496}
int dundi_ie_append_int(struct dundi_ie_data *ied, unsigned char ie, unsigned int value)
Definition: dundi-parser.c:593
int dundi_ie_append_encdata(struct dundi_ie_data *ied, unsigned char ie, unsigned char *iv, void *data, int datalen)
Definition: dundi-parser.c:541
int dundi_ie_append_raw(struct dundi_ie_data *ied, unsigned char ie, void *data, int datalen)
Definition: dundi-parser.c:486
#define DUNDI_IE_ENCDATA
Definition: dundi.h:195
#define DUNDI_IE_SIGNATURE
Definition: dundi.h:197
#define DUNDI_IE_SHAREDKEY
Definition: dundi.h:196
#define DUNDI_IE_KEYCRC32
Definition: dundi.h:198
#define DUNDI_COMMAND_ENCRYPT
Definition: dundi.h:174
static int encrypt_memcpy(unsigned char *dst, unsigned char *src, int len, unsigned char *iv, ast_aes_encrypt_key *ecx)
Definition: pbx_dundi.c:1379
static struct dundi_peer * find_peer(dundi_eid *eid)
Definition: pbx_dundi.c:521
static int update_key(struct dundi_peer *peer)
Definition: pbx_dundi.c:1340
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:230
unsigned char txenckey[256]
Definition: pbx_dundi.c:318
uint32_t us_keycrc32
Definition: pbx_dundi.c:320
ast_aes_encrypt_key us_ecx
Definition: pbx_dundi.c:321
ast_aes_decrypt_key us_dcx
Definition: pbx_dundi.c:322
ast_aes_encrypt_key ecx
Definition: pbx_dundi.c:254

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

365{
366 ast_log(LOG_WARNING, "%s", data);
367}

References ast_log, and LOG_WARNING.

Referenced by load_module().

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

4819{
4820 struct dundi_result results[MAX_RESULTS];
4821 int res;
4822 int x=0;
4823 char req[1024];
4824 const char *dundiargs;
4825
4826 if (ast_strlen_zero(data))
4827 data = context;
4828
4829 res = dundi_lookup(results, MAX_RESULTS, chan, data, exten, 0);
4830 if (res > 0) {
4831 sort_results(results, res);
4832 for (x=0;x<res;x++) {
4833 if (ast_test_flag(results + x, DUNDI_FLAG_EXISTS)) {
4834 if (!--priority)
4835 break;
4836 }
4837 }
4838 }
4839 if (x < res) {
4840 /* Got a hit! */
4841 dundiargs = pbx_builtin_getvar_helper(chan, "DUNDIDIALARGS");
4842 /* Backwards compatibility with lookups using chan_sip even if we don't have it anymore:
4843 * At a protocol level, "SIP" will always be specified, but depending on our configuration,
4844 * we will use the user-specified channel driver (from dundi.conf) to complete the call.
4845 */
4846 if (!strcasecmp(results[x].tech, "SIP") || !strcasecmp(results[x].tech, "PJSIP")) {
4847 /* Only "SIP" is a valid technology for a DUNDi peer to communicate.
4848 * But if they tell use to use "PJSIP" instead, just interpret it as if they said "SIP" instead. */
4849 if (strcasecmp(results[x].tech, "SIP")) {
4850 ast_log(LOG_WARNING, "%s cannot be specified by DUNDi peers (peer should use SIP for DUNDi lookups instead)\n", results[x].tech);
4851 }
4852 /* Use whatever we're configured to use for SIP protocol calls. */
4853 results[x].techint = outgoing_sip_tech;
4854 ast_copy_string(results[x].tech, tech2str(outgoing_sip_tech), sizeof(results[x].tech));
4855 }
4856 /* PJSIP requires an endpoint to be specified explicitly. */
4858 char *number, *ip = ast_strdupa(results[x].dest);
4860 ast_log(LOG_WARNING, "PJSIP calls require an endpoint to be specified explicitly (use the pjsip_outgoing_endpoint option in dundi.conf)\n");
4861 return -1;
4862 }
4863 /* Take IP/number and turn it into sip:number@IP */
4864 if (ast_strlen_zero(ip)) {
4865 ast_log(LOG_WARNING, "PJSIP destination is empty?\n");
4866 return -1;
4867 }
4868 number = strsep(&ip, "/");
4869 snprintf(req, sizeof(req), "%s/%s/sip:%s@%s,,%s", results[x].tech, pjsip_outgoing_endpoint, S_OR(number, ""), ip, S_OR(dundiargs, ""));
4870 ast_debug(1, "Finalized PJSIP Dial: %s\n", req);
4871 } else { /* SIP, or something else. */
4872 snprintf(req, sizeof(req), "%s/%s,,%s", results[x].tech, results[x].dest, S_OR(dundiargs, ""));
4873 }
4874 res = ast_pbx_exec_application(chan, "Dial", req);
4875 } else {
4876 res = -1;
4877 }
4878 return res;
4879}
@ DUNDI_PROTO_PJSIP
Definition: dundi.h:63
@ DUNDI_FLAG_EXISTS
Definition: dundi.h:70
char * strsep(char **str, const char *delims)
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
int ast_pbx_exec_application(struct ast_channel *chan, const char *app_name, const char *app_args)
Execute an application.
Definition: pbx_app.c:501
static int outgoing_sip_tech
Definition: pbx_dundi.c:211
static char pjsip_outgoing_endpoint[80]
Definition: pbx_dundi.c:212
#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
Number structure.
Definition: app_followme.c:154

References ast_copy_string(), ast_debug, ast_log, ast_pbx_exec_application(), ast_strdupa, ast_strlen_zero(), ast_test_flag, voicemailpwcheck::context, dundi_result::dest, DUNDI_FLAG_EXISTS, dundi_lookup(), DUNDI_PROTO_PJSIP, LOG_WARNING, MAX_RESULTS, outgoing_sip_tech, pbx_builtin_getvar_helper(), pjsip_outgoing_endpoint, priority, S_OR, sort_results(), strsep(), dundi_result::tech, tech2str(), and dundi_result::techint.

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

4809{
4810 return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_EXISTS);
4811}

References voicemailpwcheck::context, DUNDI_FLAG_EXISTS, dundi_helper(), and priority.

◆ dundi_flush()

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

Definition at line 2363 of file pbx_dundi.c.

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

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

4790{
4791 struct dundi_result results[MAX_RESULTS];
4792 int res;
4793 int x;
4794 int found = 0;
4795 if (ast_strlen_zero(data))
4796 data = context;
4797
4798 res = dundi_lookup(results, MAX_RESULTS, chan, data, exten, 0);
4799 for (x=0;x<res;x++) {
4800 if (ast_test_flag(results + x, flag))
4801 found++;
4802 }
4803 if (found >= priority)
4804 return 1;
4805 return 0;
4806}
long int flag
Definition: f2c.h:83

References ast_strlen_zero(), ast_test_flag, voicemailpwcheck::context, dundi_lookup(), MAX_RESULTS, 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 3397 of file pbx_dundi.c.

3398{
3399 struct dundi_peer *p;
3400 if (!ast_eid_cmp(eid, us)) {
3402 return;
3403 }
3406 if (!ast_eid_cmp(&p->eid, eid)) {
3407 if (has_permission(&p->include, context))
3409 else
3411 break;
3412 }
3413 }
3414 if (!p)
3417}

References ast_eid_cmp(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, voicemailpwcheck::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 3932 of file pbx_dundi.c.

3933{
3934 struct dundi_hint_metadata hmd;
3935 dundi_eid *avoid[1] = { NULL, };
3936 int direct[1] = { 0, };
3937 int expiration = dundi_cache_time;
3938 memset(&hmd, 0, sizeof(hmd));
3940 return dundi_lookup_internal(result, maxret, chan, dcontext, number, dundi_ttl, 0, &hmd, &expiration, cbypass, 0, NULL, avoid, direct);
3941}
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:3830

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(), dundi_helper(), dundi_query_read(), and dundifunc_read().

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

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

585{
586 struct ast_flags flags = {0};
587 int x;
588 if (!ast_strlen_zero(map->lcontext)) {
589 if (ast_exists_extension(NULL, map->lcontext, called_number, 1, NULL))
591 if (ast_canmatch_extension(NULL, map->lcontext, called_number, 1, NULL))
593 if (ast_matchmore_extension(NULL, map->lcontext, called_number, 1, NULL))
595 if (ast_ignore_pattern(map->lcontext, called_number))
597
598 /* Clearly we can't say 'don't ask' anymore if we found anything... */
601
603 /* Skip partial answers */
605 }
607 struct varshead headp;
608 struct ast_var_t *newvariable;
609 ast_set_flag(&flags, map->options & 0xffff);
610 ast_copy_flags(dr + anscnt, &flags, AST_FLAGS_ALL);
611 dr[anscnt].techint = map->tech;
612 dr[anscnt].expiration = dundi_cache_time;
613 ast_copy_string(dr[anscnt].tech, tech2str(map->tech), sizeof(dr[anscnt].tech));
614 dr[anscnt].eid = *us_eid;
615 ast_eid_to_str(dr[anscnt].eid_str, sizeof(dr[anscnt].eid_str), &dr[anscnt].eid);
616 if (ast_test_flag(&flags, DUNDI_FLAG_EXISTS)) {
618 if ((newvariable = ast_var_assign("NUMBER", called_number))) {
619 AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
620 }
621 if ((newvariable = ast_var_assign("EID", dr[anscnt].eid_str))) {
622 AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
623 }
624 if ((newvariable = ast_var_assign("SECRET", cursecret))) {
625 AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
626 }
627 if ((newvariable = ast_var_assign("IPADDR", ipaddr))) {
628 AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
629 }
630 pbx_substitute_variables_varshead(&headp, map->dest, dr[anscnt].dest, sizeof(dr[anscnt].dest));
631 dr[anscnt].weight = get_mapping_weight(map, &headp);
632 while ((newvariable = AST_LIST_REMOVE_HEAD(&headp, entries)))
633 ast_var_delete(newvariable);
634 } else {
635 dr[anscnt].dest[0] = '\0';
636 dr[anscnt].weight = get_mapping_weight(map, NULL);
637 }
638 anscnt++;
639 } else {
640 /* No answers... Find the fewest number of digits from the
641 number for which we have no answer. */
642 char tmp[AST_MAX_EXTENSION + 1] = "";
643 for (x = 0; x < (sizeof(tmp) - 1); x++) {
644 tmp[x] = called_number[x];
645 if (!tmp[x])
646 break;
647 if (!ast_canmatch_extension(NULL, map->lcontext, tmp, 1, NULL)) {
648 /* Oops found something we can't match. If this is longer
649 than the running hint, we have to consider it */
650 if (strlen(tmp) > strlen(hmd->exten)) {
651 ast_copy_string(hmd->exten, tmp, sizeof(hmd->exten));
652 }
653 break;
654 }
655 }
656 }
657 }
658 return anscnt;
659}
#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:2471
@ DUNDI_FLAG_MATCHMORE
Definition: dundi.h:72
@ DUNDI_FLAG_IGNOREPAT
Definition: dundi.h:76
#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:4175
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:4190
int ast_ignore_pattern(const char *context, const char *pattern)
Checks to see if a number should be ignored.
Definition: pbx.c:6879
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:4195
static int get_mapping_weight(struct dundi_mapping *map, struct varshead *headp)
Definition: pbx_dundi.c:565
static char ipaddr[80]
Definition: pbx_dundi.c:210
struct ast_var_t::@211 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 663 of file pbx_dundi.c.

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

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

4882{
4883 return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_MATCHMORE);
4884}

References voicemailpwcheck::context, DUNDI_FLAG_MATCHMORE, dundi_helper(), and priority.

◆ dundi_precache()

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

Pre-cache to push upstream peers.

Definition at line 4074 of file pbx_dundi.c.

4075{
4076 dundi_eid *avoid[1] = { NULL, };
4078}
static int dundi_precache_internal(const char *context, const char *number, int ttl, dundi_eid *avoids[])
Definition: pbx_dundi.c:4002

References voicemailpwcheck::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 3978 of file pbx_dundi.c.

3979{
3980 struct dundi_mapping *cur;
3981 struct ast_context *con;
3982 struct ast_exten *e;
3983
3984 AST_LIST_TRAVERSE(&mappings, cur, list) {
3985 ast_log(LOG_NOTICE, "Should precache context '%s'\n", cur->dcontext);
3987 con = NULL;
3988 while ((con = ast_walk_contexts(con))) {
3989 if (strcasecmp(cur->lcontext, ast_get_context_name(con)))
3990 continue;
3991 /* Found the match, now queue them all up */
3992 ast_rdlock_context(con);
3993 e = NULL;
3994 while ((e = ast_walk_context_extensions(con, e)))
3996 ast_unlock_context(con);
3997 }
3999 }
4000}
struct ast_context * ast_walk_contexts(struct ast_context *con)
Definition: extconf.c:4024
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:8491
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.
Definition: pbx.c:8468
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.
Definition: pbx.c:8473
const char * ast_get_extension_name(struct ast_exten *exten)
Definition: pbx.c:8509
int ast_rdlock_context(struct ast_context *con)
Read locks a given context.
Definition: pbx.c:8486
static void reschedule_precache(const char *number, const char *context, int expiration)
Definition: pbx_dundi.c:3943
ast_context: An extension 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 4002 of file pbx_dundi.c.

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

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(), voicemailpwcheck::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 727 of file pbx_dundi.c.

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

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

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

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

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

4128{
4129 dundi_eid *avoid[1] = { NULL, };
4130 struct dundi_hint_metadata hmd;
4131 memset(&hmd, 0, sizeof(hmd));
4132 return dundi_query_eid_internal(dei, dcontext, &eid, &hmd, dundi_ttl, 0, avoid);
4133}
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:4080

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

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

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,
char *  buf,
size_t  len 
)
static

Definition at line 4221 of file pbx_dundi.c.

4222{
4227 );
4228 struct ast_flags opts = { 0, };
4229 char *parse;
4230 struct dundi_result_datastore *drds;
4231 struct ast_datastore *datastore;
4232
4233 if (ast_strlen_zero(data)) {
4234 ast_log(LOG_WARNING, "DUNDIQUERY requires an argument (number)\n");
4235 return -1;
4236 }
4237
4238 if (!chan) {
4239 ast_log(LOG_ERROR, "DUNDIQUERY can not be used without a channel!\n");
4240 return -1;
4241 }
4242
4243 parse = ast_strdupa(data);
4244
4246
4247 if (!ast_strlen_zero(args.options))
4249
4250 if (ast_strlen_zero(args.context))
4251 args.context = "e164";
4252
4253 if (!(drds = ast_calloc(1, sizeof(*drds)))) {
4254 return -1;
4255 }
4256
4257 drds->id = ast_atomic_fetchadd_int((int *) &dundi_result_id, 1);
4258 snprintf(buf, len, "%u", drds->id);
4259
4260 if (!(datastore = ast_datastore_alloc(&dundi_result_datastore_info, buf))) {
4261 drds_destroy(drds);
4262 return -1;
4263 }
4264
4265 datastore->data = drds;
4266
4267 drds->num_results = dundi_lookup(drds->results, ARRAY_LEN(drds->results), NULL, args.context,
4268 args.number, ast_test_flag(&opts, OPT_BYPASS_CACHE));
4269
4270 if (drds->num_results > 0)
4271 sort_results(drds->results, drds->num_results);
4272
4273 ast_channel_lock(chan);
4274 ast_channel_datastore_add(chan, datastore);
4275 ast_channel_unlock(chan);
4276
4277 return 0;
4278}
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2404
#define ast_channel_lock(chan)
Definition: channel.h:2968
#define ast_channel_unlock(chan)
Definition: channel.h:2969
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:85
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:3066
#define LOG_ERROR
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:757
static const struct ast_app_option dundi_query_opts[128]
Definition: pbx_dundi.c:4141
static unsigned int dundi_result_id
Definition: pbx_dundi.c:4197
static const struct ast_datastore_info dundi_result_datastore_info
Definition: pbx_dundi.c:4216
Structure for a data store object.
Definition: datastore.h:64
void * data
Definition: datastore.h:66
struct dundi_result results[MAX_RESULTS]
Definition: pbx_dundi.c:4200
const char * args
static struct test_options options

References args, ARRAY_LEN, AST_APP_ARG, ast_app_parse_options(), ast_atomic_fetchadd_int(), ast_calloc, ast_channel_datastore_add(), ast_channel_lock, ast_channel_unlock, ast_datastore_alloc, AST_DECLARE_APP_ARGS, ast_log, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_test_flag, buf, voicemailpwcheck::context, ast_datastore::data, drds_destroy(), dundi_lookup(), dundi_query_opts, dundi_result_datastore_info, dundi_result_id, dundi_result_datastore::id, len(), LOG_ERROR, LOG_WARNING, NULL, dundi_result_datastore::num_results, OPT_BYPASS_CACHE, options, dundi_result_datastore::results, and sort_results().

◆ dundi_query_thread()

static void * dundi_query_thread ( void *  data)
static

Definition at line 760 of file pbx_dundi.c.

761{
762 struct dundi_query_state *st = data;
763 struct dundi_entity_info dei;
764 struct dundi_ie_data ied;
765 struct dundi_hint_metadata hmd;
766 char eid_str[20];
767 int res;
768
769 ast_debug(1, "Whee, looking up '%s@%s' for '%s'\n", st->called_number, st->called_context,
770 st->eids[0] ? ast_eid_to_str(eid_str, sizeof(eid_str), st->eids[0]) : "ourselves");
771 memset(&ied, 0, sizeof(ied));