Asterisk - The Open Source Telephony Project GIT-master-a358458
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:476
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:342
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:536

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:2980
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:2385
#define ast_channel_lock(chan)
Definition: channel.h:2922
#define ast_channel_unlock(chan)
Definition: channel.h:2923
#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:3056
#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));
772 memset(&dei, 0, sizeof(dei));
773 memset(&hmd, 0, sizeof(hmd));
774 if (!ast_eid_cmp(&st->trans->us_eid, &st->reqeid)) {
775 /* Ooh, it's us! */
776 ast_debug(1, "Neat, someone look for us!\n");
777 ast_copy_string(dei.orgunit, dept, sizeof(dei.orgunit));
778 ast_copy_string(dei.org, org, sizeof(dei.org));
779 ast_copy_string(dei.locality, locality, sizeof(dei.locality));
780 ast_copy_string(dei.stateprov, stateprov, sizeof(dei.stateprov));
781 ast_copy_string(dei.country, country, sizeof(dei.country));
782 ast_copy_string(dei.email, email, sizeof(dei.email));
783 ast_copy_string(dei.phone, phone, sizeof(dei.phone));
784 res = 1;
785 } else {
786 /* If we do not have a canonical result, keep looking */
787 res = dundi_query_eid_internal(&dei, st->called_context, &st->reqeid, &hmd, st->ttl, 1, st->eids);
788 }
790 if (ast_test_flag(st->trans, FLAG_DEAD)) {
791 ast_debug(1, "Our transaction went away!\n");
792 st->trans->thread = 0;
793 destroy_trans(st->trans, 0);
794 } else {
795 if (res) {
796 dundi_ie_append_str(&ied, DUNDI_IE_DEPARTMENT, dei.orgunit);
798 dundi_ie_append_str(&ied, DUNDI_IE_LOCALITY, dei.locality);
799 dundi_ie_append_str(&ied, DUNDI_IE_STATE_PROV, dei.stateprov);
800 dundi_ie_append_str(&ied, DUNDI_IE_COUNTRY, dei.country);
801 dundi_ie_append_str(&ied, DUNDI_IE_EMAIL, dei.email);
802 dundi_ie_append_str(&ied, DUNDI_IE_PHONE, dei.phone);
803 if (!ast_strlen_zero(dei.ipaddr))
804 dundi_ie_append_str(&ied, DUNDI_IE_IPADDR, dei.ipaddr);
805 }
806 dundi_ie_append_hint(&ied, DUNDI_IE_HINT, hmd.flags, hmd.exten);
808 st->trans->thread = 0;
809 }
811 ast_free(st);
812 return NULL;
813}
#define DUNDI_IE_COUNTRY
Definition: dundi.h:205
#define DUNDI_IE_IPADDR
Definition: dundi.h:208
#define DUNDI_IE_DEPARTMENT
Definition: dundi.h:201
#define DUNDI_IE_ORGANIZATION
Definition: dundi.h:202
#define DUNDI_IE_LOCALITY
Definition: dundi.h:203
#define DUNDI_IE_PHONE
Definition: dundi.h:207
#define DUNDI_IE_EMAIL
Definition: dundi.h:206
#define DUNDI_IE_STATE_PROV
Definition: dundi.h:204
static char country[80]
Definition: pbx_dundi.c:205
static char phone[80]
Definition: pbx_dundi.c:207
static char locality[80]
Definition: pbx_dundi.c:203
static char email[80]
Definition: pbx_dundi.c:206
static char stateprov[80]
Definition: pbx_dundi.c:204
static char org[80]
Definition: pbx_dundi.c:202
static char dept[80]
Definition: pbx_dundi.c:201

References ast_copy_string(), ast_debug, ast_eid_cmp(), ast_eid_to_str(), ast_free, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_strlen_zero(), ast_test_flag, dundi_query_state::called_context, dundi_query_state::called_number, dundi_entity_info::country, country, dept, destroy_trans(), DUNDI_COMMAND_EIDRESPONSE, dundi_ie_append_hint(), dundi_ie_append_str(), DUNDI_IE_COUNTRY, DUNDI_IE_DEPARTMENT, DUNDI_IE_EMAIL, DUNDI_IE_HINT, DUNDI_IE_IPADDR, DUNDI_IE_LOCALITY, DUNDI_IE_ORGANIZATION, DUNDI_IE_PHONE, DUNDI_IE_STATE_PROV, dundi_query_eid_internal(), dundi_send(), dundi_query_state::eids, dundi_entity_info::email, email, dundi_hint_metadata::exten, FLAG_DEAD, dundi_hint_metadata::flags, dundi_entity_info::ipaddr, dundi_entity_info::locality, locality, NULL, dundi_entity_info::org, org, dundi_entity_info::orgunit, dundi_entity_info::phone, phone, dundi_query_state::reqeid, dundi_entity_info::stateprov, stateprov, dundi_transaction::thread, dundi_query_state::trans, dundi_query_state::ttl, and dundi_transaction::us_eid.

Referenced by dundi_answer_entity().

◆ dundi_reject()

static void dundi_reject ( struct dundi_hdr h,
struct ast_sockaddr sin 
)
static

Definition at line 461 of file pbx_dundi.c.

462{
463 struct {
464 struct dundi_packet pack;
465 struct dundi_hdr hdr;
466 } tmp;
467 struct dundi_transaction trans;
468 /* Never respond to an INVALID with another INVALID */
470 return;
471 memset(&tmp, 0, sizeof(tmp));
472 memset(&trans, 0, sizeof(trans));
473 ast_sockaddr_copy(&trans.addr, sin);
474 tmp.hdr.strans = h->dtrans;
475 tmp.hdr.dtrans = h->strans;
476 tmp.hdr.iseqno = h->oseqno;
477 tmp.hdr.oseqno = h->iseqno;
478 tmp.hdr.cmdresp = DUNDI_COMMAND_INVALID;
479 tmp.hdr.cmdflags = 0;
480 tmp.pack.h = (struct dundi_hdr *)tmp.pack.data;
481 tmp.pack.datalen = sizeof(struct dundi_hdr);
482 tmp.pack.parent = &trans;
483 dundi_xmit(&tmp.pack);
484}
#define DUNDI_COMMAND_INVALID
Definition: dundi.h:168
static int dundi_xmit(struct dundi_packet *pack)
Definition: pbx_dundi.c:3175
unsigned short strans
Definition: dundi.h:35
unsigned short dtrans
Definition: dundi.h:36

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

Referenced by handle_frame().

◆ dundi_result_read()

static int dundi_result_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)
static

Definition at line 4285 of file pbx_dundi.c.

4286{
4288 AST_APP_ARG(id);
4289 AST_APP_ARG(resultnum);
4290 );
4291 char *parse;
4292 unsigned int num;
4293 struct dundi_result_datastore *drds;
4294 struct ast_datastore *datastore;
4295 int res = -1;
4296
4297 if (ast_strlen_zero(data)) {
4298 ast_log(LOG_WARNING, "DUNDIRESULT requires an argument (id and resultnum)\n");
4299 goto finish;
4300 }
4301
4302 if (!chan) {
4303 ast_log(LOG_ERROR, "DUNDRESULT can not be used without a channel!\n");
4304 goto finish;
4305 }
4306
4307 parse = ast_strdupa(data);
4308
4310
4311 if (ast_strlen_zero(args.id)) {
4312 ast_log(LOG_ERROR, "A result ID must be provided to DUNDIRESULT\n");
4313 goto finish;
4314 }
4315
4316 if (ast_strlen_zero(args.resultnum)) {
4317 ast_log(LOG_ERROR, "A result number must be given to DUNDIRESULT!\n");
4318 goto finish;
4319 }
4320
4321 ast_channel_lock(chan);
4323 ast_channel_unlock(chan);
4324
4325 if (!datastore) {
4326 ast_log(LOG_WARNING, "No DUNDi results found for query ID '%s'\n", args.id);
4327 goto finish;
4328 }
4329
4330 drds = datastore->data;
4331
4332 if (!strcasecmp(args.resultnum, "getnum")) {
4333 snprintf(buf, len, "%d", drds->num_results < 0 ? 0 : drds->num_results);
4334 res = 0;
4335 goto finish;
4336 }
4337
4338 if (sscanf(args.resultnum, "%30u", &num) != 1) {
4339 ast_log(LOG_ERROR, "Invalid value '%s' for resultnum to DUNDIRESULT!\n",
4340 args.resultnum);
4341 goto finish;
4342 }
4343
4344 if (num && drds->num_results > 0 && num <= drds->num_results) {
4345 snprintf(buf, len, "%s/%s", drds->results[num - 1].tech, drds->results[num - 1].dest);
4346 res = 0;
4347 } else
4348 ast_log(LOG_WARNING, "Result number %u is not valid for DUNDi query results for ID %s!\n", num, args.id);
4349
4350finish:
4351 return res;
4352}
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2399

References args, AST_APP_ARG, ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, AST_DECLARE_APP_ARGS, ast_log, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), buf, ast_datastore::data, dundi_result::dest, dundi_result_datastore_info, len(), LOG_ERROR, LOG_WARNING, dundi_result_datastore::num_results, dundi_result_datastore::results, and dundi_result::tech.

◆ dundi_rexmit()

static int dundi_rexmit ( const void *  data)
static

Definition at line 3291 of file pbx_dundi.c.

3292{
3293 struct dundi_packet *pack = (struct dundi_packet *)data;
3294 int res;
3296 if (pack->retrans < 1) {
3297 pack->retransid = -1;
3298 if (!ast_test_flag(pack->parent, FLAG_ISQUAL)) {
3299 ast_log(LOG_NOTICE, "Max retries exceeded to host '%s' msg %d on call %d\n",
3300 ast_sockaddr_stringify(&pack->parent->addr), pack->h->oseqno, ntohs(pack->h->strans));
3301 }
3302 destroy_trans(pack->parent, 1);
3303 res = 0;
3304 } else {
3305 /* Decrement retransmission, try again */
3306 pack->retrans--;
3307 dundi_xmit(pack);
3308 res = 1;
3309 }
3311 return res;
3312}
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:256

References dundi_transaction::addr, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log, ast_sockaddr_stringify(), ast_test_flag, dundi_packet::data, destroy_trans(), dundi_xmit(), FLAG_ISQUAL, dundi_packet::h, LOG_NOTICE, dundi_hdr::oseqno, dundi_packet::parent, dundi_packet::retrans, dundi_packet::retransid, and dundi_hdr::strans.

Referenced by dundi_send().

◆ dundi_send()

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

Definition at line 3314 of file pbx_dundi.c.

3315{
3316 struct dundi_packet *pack;
3317 int res;
3318 int len;
3319 char eid_str[20];
3320 len = sizeof(struct dundi_packet) + sizeof(struct dundi_hdr) + (ied ? ied->pos : 0);
3321 /* Reserve enough space for encryption */
3322 if (ast_test_flag(trans, FLAG_ENCRYPT))
3323 len += 384;
3324 pack = ast_calloc(1, len);
3325 if (pack) {
3326 pack->h = (struct dundi_hdr *)(pack->data);
3327 pack->retransid = -1;
3328 if (cmdresp != DUNDI_COMMAND_ACK) {
3329 pack->retransid = ast_sched_add(sched, trans->retranstimer, dundi_rexmit, pack);
3330 pack->retrans = DUNDI_DEFAULT_RETRANS - 1;
3331 AST_LIST_INSERT_HEAD(&trans->packets, pack, list);
3332 }
3333 pack->parent = trans;
3334 pack->h->strans = htons(trans->strans);
3335 pack->h->dtrans = htons(trans->dtrans);
3336 pack->h->iseqno = trans->iseqno;
3337 pack->h->oseqno = trans->oseqno;
3338 pack->h->cmdresp = cmdresp;
3339 pack->datalen = sizeof(struct dundi_hdr);
3340 if (ied) {
3341 memcpy(pack->h->ies, ied->buf, ied->pos);
3342 pack->datalen += ied->pos;
3343 }
3344 if (final) {
3345 pack->h->cmdresp |= DUNDI_COMMAND_FINAL;
3346 ast_set_flag(trans, FLAG_FINAL);
3347 }
3348 pack->h->cmdflags = flags;
3349 if (cmdresp != DUNDI_COMMAND_ACK) {
3350 trans->oseqno++;
3351 trans->oseqno = trans->oseqno % 256;
3352 }
3353 trans->aseqno = trans->iseqno;
3354 /* If we have their public key, encrypt */
3355 if (ast_test_flag(trans, FLAG_ENCRYPT)) {
3356 switch(cmdresp) {
3365 if (dundidebug)
3366 dundi_showframe(pack->h, 2, &trans->addr, pack->datalen - sizeof(struct dundi_hdr));
3367 res = dundi_encrypt(trans, pack);
3368 break;
3369 default:
3370 res = 0;
3371 }
3372 } else
3373 res = 0;
3374 if (!res)
3375 res = dundi_xmit(pack);
3376 if (res)
3377 ast_log(LOG_NOTICE, "Failed to send packet to '%s'\n", ast_eid_to_str(eid_str, sizeof(eid_str), &trans->them_eid));
3378
3380 ast_free(pack);
3381 return res;
3382 }
3383 return -1;
3384}
if(!yyg->yy_init)
Definition: ast_expr2f.c:854
void dundi_showframe(struct dundi_hdr *fhi, int rx, struct ast_sockaddr *sin, int datalen)
Definition: dundi-parser.c:434
#define DUNDI_COMMAND_PRECACHERQ
Definition: dundi.h:166
#define DUNDI_DEFAULT_RETRANS
Definition: dundi.h:216
#define DUNDI_COMMAND_FINAL
Definition: dundi.h:159
#define DUNDI_COMMAND_REGRESPONSE
Definition: dundi.h:172
static int dundi_encrypt(struct dundi_transaction *trans, struct dundi_packet *pack)
Definition: pbx_dundi.c:1434
static int dundi_rexmit(const void *data)
Definition: pbx_dundi.c:3291
unsigned char buf[8192]
Definition: dundi-parser.h:56
unsigned char iseqno
Definition: pbx_dundi.c:264
unsigned short dtrans
Definition: pbx_dundi.c:263
unsigned char oseqno
Definition: pbx_dundi.c:266
unsigned char aseqno
Definition: pbx_dundi.c:267

References dundi_transaction::addr, dundi_transaction::aseqno, ast_calloc, ast_eid_to_str(), ast_free, AST_LIST_INSERT_HEAD, ast_log, ast_sched_add(), ast_set_flag, ast_test_flag, dundi_ie_data::buf, dundi_hdr::cmdflags, dundi_hdr::cmdresp, dundi_packet::data, dundi_packet::datalen, dundi_hdr::dtrans, dundi_transaction::dtrans, DUNDI_COMMAND_ACK, DUNDI_COMMAND_DPDISCOVER, DUNDI_COMMAND_DPRESPONSE, DUNDI_COMMAND_EIDQUERY, DUNDI_COMMAND_EIDRESPONSE, DUNDI_COMMAND_FINAL, DUNDI_COMMAND_PRECACHERP, DUNDI_COMMAND_PRECACHERQ, DUNDI_COMMAND_REGREQ, DUNDI_COMMAND_REGRESPONSE, DUNDI_DEFAULT_RETRANS, dundi_encrypt(), dundi_rexmit(), dundi_showframe(), dundi_xmit(), dundidebug, FLAG_ENCRYPT, FLAG_FINAL, dundi_packet::h, dundi_hdr::ies, if(), dundi_hdr::iseqno, dundi_transaction::iseqno, len(), dundi_packet::list, LOG_NOTICE, dundi_hdr::oseqno, dundi_transaction::oseqno, dundi_transaction::packets, dundi_packet::parent, dundi_ie_data::pos, dundi_packet::retrans, dundi_packet::retransid, dundi_transaction::retranstimer, dundi_hdr::strans, dundi_transaction::strans, and dundi_transaction::them_eid.

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

◆ dundi_set_debug()

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

Definition at line 2310 of file pbx_dundi.c.

2311{
2312 switch (cmd) {
2313 case CLI_INIT:
2314 e->command = "dundi set debug {on|off}";
2315 e->usage =
2316 "Usage: dundi set debug {on|off}\n"
2317 " Enables/Disables dumping of DUNDi packets for debugging purposes\n";
2318 return NULL;
2319 case CLI_GENERATE:
2320 return NULL;
2321 }
2322
2323 if (a->argc != e->args) {
2324 return CLI_SHOWUSAGE;
2325 }
2326 if (!strncasecmp(a->argv[e->args -1], "on", 2)) {
2327 dundidebug = 1;
2328 ast_cli(a->fd, "DUNDi Debugging Enabled\n");
2329 } else {
2330 dundidebug = 0;
2331 ast_cli(a->fd, "DUNDi Debugging Disabled\n");
2332 }
2333 return CLI_SUCCESS;
2334}
int args
This gets set in ast_cli_register()
Definition: cli.h:185

References a, ast_cli_entry::args, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dundidebug, NULL, and ast_cli_entry::usage.

◆ dundi_show_cache()

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

Definition at line 2961 of file pbx_dundi.c.

2962{
2963#define FORMAT2 "%-12.12s %-16.16s %-10.10s %-18s %-7s %s\n"
2964#define FORMAT "%-12.12s %-16.16s %6d sec %-18s %-7d %s/%s (%s)\n"
2965 struct ast_db_entry *db_tree, *db_entry;
2966 int cnt = 0;
2967 time_t ts, now;
2968 dundi_eid src_eid;
2969 char src_eid_str[20];
2970 int expiry, tech, weight;
2971 struct ast_flags flags;
2972 char fs[256];
2973 int length;
2974 char *ptr, *term, *src, *number, *context, *dst;
2975
2976 switch (cmd) {
2977 case CLI_INIT:
2978 e->command = "dundi show cache";
2979 e->usage =
2980 "Usage: dundi show cache\n"
2981 " Lists all DUNDi cache entries.\n";
2982 return NULL;
2983 case CLI_GENERATE:
2984 return NULL;
2985 }
2986
2987 if (a->argc != 3) {
2988 return CLI_SHOWUSAGE;
2989 }
2990
2991 time(&now);
2992 db_tree = ast_db_gettree("dundi/cache", NULL);
2993 ast_cli(a->fd, FORMAT2, "Number", "Context", "Expiration", "From", "Weight", "Destination (Flags)");
2994 for (db_entry = db_tree; db_entry; db_entry = db_entry->next) {
2995 char *rest;
2996
2997 if ((strncmp(db_entry->key, "/dundi/cache/hint/", 18) == 0) || ast_get_time_t(db_entry->data, &ts, 0, &length)) {
2998 continue;
2999 }
3000
3001 expiry = ts - now;
3002
3003 if (expiry <= 0) {
3004 continue;
3005 }
3006
3007 ptr = db_entry->key + sizeof("/dundi/cache");
3008 strtok_r(ptr, "/", &rest);
3009 number = strtok_r(NULL, "/", &rest);
3010 context = strtok_r(NULL, "/", &rest);
3011 ptr = strtok_r(NULL, "/", &rest);
3012
3013 if (*ptr != 'e') {
3014 continue;
3015 }
3016
3017 ptr = db_entry->data + length + 1;
3018
3019 if ((sscanf(ptr, "%30u/%30d/%30d/%n", &(flags.flags), &weight, &tech, &length) != 3)) {
3020 continue;
3021 }
3022
3023 ptr += length;
3024 dst = ptr;
3025 term = strchr(ptr, '|');
3026
3027 if (!term) {
3028 continue;
3029 }
3030
3031 /* Ok, at this point we know we aren't going to skp the entry, so we go ahead and increment the count. */
3032 cnt++;
3033
3034 *term = '\0';
3035 src = strrchr(ptr, '/');
3036 dundi_eid_zero(&src_eid);
3037
3038 if (src) {
3039 *src = '\0';
3040 src++;
3041 dundi_str_short_to_eid(&src_eid, src);
3042 ast_eid_to_str(src_eid_str, sizeof(src_eid_str), &src_eid);
3043 }
3044
3045 ast_cli(a->fd, FORMAT, number, context, expiry, src_eid_str, weight, tech2str(tech), dst, dundi_flags2str(fs, sizeof(fs), flags.flags));
3046 }
3047
3048 ast_cli(a->fd, "Number of entries: %d\n", cnt);
3049 ast_db_freetree(db_tree);
3050
3051 return CLI_SUCCESS;
3052#undef FORMAT
3053#undef FORMAT2
3054}
struct ast_db_entry * ast_db_gettree(const char *family, const char *keytree)
Get a list of values within the astdb tree.
Definition: main/db.c:610
void ast_db_freetree(struct ast_db_entry *entry)
Free structure created by ast_db_gettree()
Definition: main/db.c:677
#define FORMAT
#define FORMAT2
Definition: astdb.h:31
struct ast_db_entry * next
Definition: astdb.h:32
char * key
Definition: astdb.h:33
char data[0]
Definition: astdb.h:34

References a, ast_cli(), ast_db_freetree(), ast_db_gettree(), ast_eid_to_str(), ast_get_time_t(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, voicemailpwcheck::context, ast_db_entry::data, dundi_eid_zero(), dundi_flags2str(), dundi_str_short_to_eid(), ast_flags::flags, FORMAT, FORMAT2, ast_db_entry::key, ast_db_entry::next, NULL, tech2str(), ast_cli_entry::usage, and weight.

◆ dundi_show_entityid()

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

Definition at line 2833 of file pbx_dundi.c.

2834{
2835 char eid_str[20];
2836 switch (cmd) {
2837 case CLI_INIT:
2838 e->command = "dundi show entityid";
2839 e->usage =
2840 "Usage: dundi show entityid\n"
2841 " Displays the global entityid for this host.\n";
2842 return NULL;
2843 case CLI_GENERATE:
2844 return NULL;
2845 }
2846 if (a->argc != 3) {
2847 return CLI_SHOWUSAGE;
2848 }
2850 ast_eid_to_str(eid_str, sizeof(eid_str), &global_eid);
2852 ast_cli(a->fd, "Global EID for this system is '%s'\n", eid_str);
2853 return CLI_SUCCESS;
2854}

References a, ast_cli(), ast_eid_to_str(), AST_LIST_LOCK, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, global_eid, NULL, and ast_cli_entry::usage.

◆ dundi_show_hints()

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

Definition at line 3056 of file pbx_dundi.c.

3057{
3058#define FORMAT2 "%-12.12s %-16.16s %-10.10s %-18s\n"
3059#define FORMAT "%-12.12s %-16.16s %6d sec %-18s\n"
3060 struct ast_db_entry *db_tree, *db_entry;
3061 int cnt = 0;
3062 time_t ts, now;
3063 dundi_eid src_eid;
3064 char src_eid_str[20];
3065 int expiry;
3066 int length;
3067 char *ptr, *src, *number, *context;
3068
3069 switch (cmd) {
3070 case CLI_INIT:
3071 e->command = "dundi show hints";
3072 e->usage =
3073 "Usage: dundi show hints\n"
3074 " Lists all DUNDi 'DONTASK' hints in the cache.\n";
3075 return NULL;
3076 case CLI_GENERATE:
3077 return NULL;
3078 }
3079
3080 if (a->argc != 3) {
3081 return CLI_SHOWUSAGE;
3082 }
3083
3084 time(&now);
3085 db_tree = ast_db_gettree("dundi/cache/hint", NULL);
3086 ast_cli(a->fd, FORMAT2, "Prefix", "Context", "Expiration", "From");
3087
3088 for (db_entry = db_tree; db_entry; db_entry = db_entry->next) {
3089 char *rest = NULL;
3090
3091 if (ast_get_time_t(db_entry->data, &ts, 0, &length)) {
3092 continue;
3093 }
3094
3095 expiry = ts - now;
3096
3097 if (expiry <= 0) {
3098 continue;
3099 }
3100
3101 ptr = db_entry->key + sizeof("/dundi/cache/hint");
3102 src = strtok_r(ptr, "/", &rest);
3103 number = strtok_r(NULL, "/", &rest);
3104 context = strtok_r(NULL, "/", &rest);
3105 ptr = strtok_r(NULL, "/", &rest);
3106
3107 if (*ptr != 'e') {
3108 continue;
3109 }
3110
3111 cnt++;
3112 dundi_str_short_to_eid(&src_eid, src);
3113 ast_eid_to_str(src_eid_str, sizeof(src_eid_str), &src_eid);
3114 ast_cli(a->fd, FORMAT, number, context, expiry, src_eid_str);
3115 }
3116
3117 ast_cli(a->fd, "Number of entries: %d\n", cnt);
3118 ast_db_freetree(db_tree);
3119
3120 return CLI_SUCCESS;
3121#undef FORMAT
3122#undef FORMAT2
3123}

References a, ast_cli(), ast_db_freetree(), ast_db_gettree(), ast_eid_to_str(), ast_get_time_t(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, voicemailpwcheck::context, ast_db_entry::data, dundi_str_short_to_eid(), FORMAT, FORMAT2, ast_db_entry::key, ast_db_entry::next, NULL, and ast_cli_entry::usage.

◆ dundi_show_mappings()

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

Definition at line 2889 of file pbx_dundi.c.

2890{
2891#define FORMAT2 "%-12.12s %-7.7s %-12.12s %-10.10s %-5.5s %-25.25s\n"
2892#define FORMAT "%-12.12s %-7s %-12.12s %-10.10s %-5.5s %-25.25s\n"
2893 struct dundi_mapping *map;
2894 char fs[256];
2895 char weight[8];
2896 switch (cmd) {
2897 case CLI_INIT:
2898 e->command = "dundi show mappings";
2899 e->usage =
2900 "Usage: dundi show mappings\n"
2901 " Lists all known DUNDi mappings.\n";
2902 return NULL;
2903 case CLI_GENERATE:
2904 return NULL;
2905 }
2906 if (a->argc != 3) {
2907 return CLI_SHOWUSAGE;
2908 }
2910 ast_cli(a->fd, FORMAT2, "DUNDi Cntxt", "Weight", "Local Cntxt", "Options", "Tech", "Destination");
2912 snprintf(weight, sizeof(weight), "%d", get_mapping_weight(map, NULL));
2913 ast_cli(a->fd, FORMAT, map->dcontext, weight,
2914 ast_strlen_zero(map->lcontext) ? "<none>" : map->lcontext,
2915 dundi_flags2str(fs, sizeof(fs), map->options), tech2str(map->tech), map->dest);
2916 }
2918 return CLI_SUCCESS;
2919#undef FORMAT
2920#undef FORMAT2
2921}

References a, ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dundi_mapping::dcontext, dundi_mapping::dest, dundi_flags2str(), FORMAT, FORMAT2, get_mapping_weight(), dundi_mapping::lcontext, dundi_mapping::list, NULL, dundi_mapping::options, dundi_mapping::tech, tech2str(), ast_cli_entry::usage, and weight.

◆ dundi_show_peer()

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

Definition at line 2627 of file pbx_dundi.c.

2628{
2629 struct dundi_peer *peer;
2630 struct permission *p;
2631 char *order;
2632 char eid_str[20];
2633 int x, cnt;
2634 switch (cmd) {
2635 case CLI_INIT:
2636 e->command = "dundi show peer";
2637 e->usage =
2638 "Usage: dundi show peer [peer]\n"
2639 " Provide a detailed description of a specifid DUNDi peer.\n";
2640 return NULL;
2641 case CLI_GENERATE:
2642 return complete_peer_helper(a->line, a->word, a->pos, a->n, 3);
2643 }
2644 if (a->argc != 4) {
2645 return CLI_SHOWUSAGE;
2646 }
2648 AST_LIST_TRAVERSE(&peers, peer, list) {
2649 if (!strcasecmp(ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), a->argv[3]))
2650 break;
2651 }
2652 if (peer) {
2653 switch(peer->order) {
2654 case 0:
2655 order = "Primary";
2656 break;
2657 case 1:
2658 order = "Secondary";
2659 break;
2660 case 2:
2661 order = "Tertiary";
2662 break;
2663 case 3:
2664 order = "Quartiary";
2665 break;
2666 default:
2667 order = "Unknown";
2668 }
2669 ast_cli(a->fd, "Peer: %s\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
2670 ast_cli(a->fd, "Model: %s\n", model2str(peer->model));
2671 ast_cli(a->fd, "Order: %s\n", order);
2672 ast_cli(a->fd, "Host: %s\n", ast_sockaddr_isnull(&peer->addr) ? "<Unspecified>" : ast_sockaddr_stringify_host(&peer->addr));
2673 ast_cli(a->fd, "Port: %d\n", dundi_sockaddr_port(&peer->addr));
2674 ast_cli(a->fd, "Dynamic: %s\n", peer->dynamic ? "yes" : "no");
2675 ast_cli(a->fd, "Reg: %s\n", peer->registerid < 0 ? "No" : "Yes");
2676 ast_cli(a->fd, "In Key: %s\n", ast_strlen_zero(peer->inkey) ? "<None>" : peer->inkey);
2677 ast_cli(a->fd, "Out Key: %s\n", ast_strlen_zero(peer->outkey) ? "<None>" : peer->outkey);
2678 if (!AST_LIST_EMPTY(&peer->include))
2679 ast_cli(a->fd, "Include logic%s:\n", peer->model & DUNDI_MODEL_OUTBOUND ? "" : " (IGNORED)");
2680 AST_LIST_TRAVERSE(&peer->include, p, list)
2681 ast_cli(a->fd, "-- %s %s\n", p->allow ? "include" : "do not include", p->name);
2682 if (!AST_LIST_EMPTY(&peer->permit))
2683 ast_cli(a->fd, "Query logic%s:\n", peer->model & DUNDI_MODEL_INBOUND ? "" : " (IGNORED)");
2684 AST_LIST_TRAVERSE(&peer->permit, p, list)
2685 ast_cli(a->fd, "-- %s %s\n", p->allow ? "permit" : "deny", p->name);
2686 cnt = 0;
2687 for (x = 0;x < DUNDI_TIMING_HISTORY; x++) {
2688 if (peer->lookups[x]) {
2689 if (!cnt)
2690 ast_cli(a->fd, "Last few query times:\n");
2691 ast_cli(a->fd, "-- %d. %s (%d ms)\n", x + 1, peer->lookups[x], peer->lookuptimes[x]);
2692 cnt++;
2693 }
2694 }
2695 if (cnt)
2696 ast_cli(a->fd, "Average query time: %d ms\n", peer->avgms);
2697 } else
2698 ast_cli(a->fd, "No such peer '%s'\n", a->argv[3]);
2700 return CLI_SUCCESS;
2701}
static char * ast_sockaddr_stringify_host(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only, suitable for a URL (with brack...
Definition: netsock2.h:327
static uint16_t dundi_sockaddr_port(const struct ast_sockaddr *addr)
Definition: pbx_dundi.c:2615
static char * complete_peer_helper(const char *line, const char *word, int pos, int state, int rpos)
Definition: pbx_dundi.c:2423
static char * model2str(int model)
Definition: pbx_dundi.c:2409

References a, dundi_peer::addr, permission::allow, ast_cli(), ast_eid_to_str(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_sockaddr_isnull(), ast_sockaddr_stringify_host(), ast_strlen_zero(), dundi_peer::avgms, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_peer_helper(), DUNDI_MODEL_INBOUND, DUNDI_MODEL_OUTBOUND, dundi_sockaddr_port(), DUNDI_TIMING_HISTORY, dundi_peer::dynamic, dundi_peer::eid, dundi_peer::include, dundi_peer::inkey, permission::list, dundi_peer::lookups, dundi_peer::lookuptimes, dundi_peer::model, model2str(), permission::name, NULL, order, dundi_peer::order, dundi_peer::outkey, dundi_peer::permit, dundi_peer::registerid, and ast_cli_entry::usage.

◆ dundi_show_peers()

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

Definition at line 2703 of file pbx_dundi.c.

2704{
2705#define FORMAT2 "%-20.20s %-41s %-6.6s %-10.10s %-8.8s %-15.15s\n"
2706#define FORMAT "%-20.20s %-41s %s %-6d %-10.10s %-8.8s %-15.15s\n"
2707 struct dundi_peer *peer;
2708 int registeredonly=0;
2709 char avgms[20];
2710 char eid_str[20];
2711 int online_peers = 0;
2712 int offline_peers = 0;
2713 int unmonitored_peers = 0;
2714 int total_peers = 0;
2715 switch (cmd) {
2716 case CLI_INIT:
2717 e->command = "dundi show peers [registered|include|exclude|begin]";
2718 e->usage =
2719 "Usage: dundi show peers [registered|include|exclude|begin]\n"
2720 " Lists all known DUNDi peers.\n"
2721 " If 'registered' is present, only registered peers are shown.\n";
2722 return NULL;
2723 case CLI_GENERATE:
2724 return NULL;
2725 }
2726
2727 if ((a->argc != 3) && (a->argc != 4) && (a->argc != 5)) {
2728 return CLI_SHOWUSAGE;
2729 }
2730 if ((a->argc == 4)) {
2731 if (!strcasecmp(a->argv[3], "registered")) {
2732 registeredonly = 1;
2733 } else {
2734 return CLI_SHOWUSAGE;
2735 }
2736 }
2738 ast_cli(a->fd, FORMAT2, "EID", "Host", "Port", "Model", "AvgTime", "Status");
2739 AST_LIST_TRAVERSE(&peers, peer, list) {
2740 char status[64];
2741 int print_line = -1;
2742 char srch[2000];
2743
2744 total_peers++;
2745 if (registeredonly && ast_sockaddr_isnull(&peer->addr)) {
2746 continue;
2747 }
2748 if (peer->maxms) {
2749 if (peer->lastms < 0) {
2750 strcpy(status, "UNREACHABLE");
2751 offline_peers++;
2752 }
2753 else if (peer->lastms > peer->maxms) {
2754 snprintf(status, sizeof(status), "LAGGED (%d ms)", peer->lastms);
2755 offline_peers++;
2756 }
2757 else if (peer->lastms) {
2758 snprintf(status, sizeof(status), "OK (%d ms)", peer->lastms);
2759 online_peers++;
2760 }
2761 else {
2762 strcpy(status, "UNKNOWN");
2763 offline_peers++;
2764 }
2765 } else {
2766 strcpy(status, "Unmonitored");
2767 unmonitored_peers++;
2768 }
2769 if (peer->avgms)
2770 snprintf(avgms, sizeof(avgms), "%d ms", peer->avgms);
2771 else
2772 strcpy(avgms, "Unavail");
2773 snprintf(srch, sizeof(srch), FORMAT, ast_eid_to_str(eid_str, sizeof(eid_str),
2774 &peer->eid), dundi_sockaddr_stringify_host(&peer->addr),
2775 peer->dynamic ? "(D)" : "(S)", dundi_sockaddr_port(&peer->addr), model2str(peer->model), avgms, status);
2776
2777 if (a->argc == 5) {
2778 if (!strcasecmp(a->argv[3],"include") && strstr(srch,a->argv[4])) {
2779 print_line = -1;
2780 } else if (!strcasecmp(a->argv[3],"exclude") && !strstr(srch,a->argv[4])) {
2781 print_line = 1;
2782 } else if (!strcasecmp(a->argv[3],"begin") && !strncasecmp(srch,a->argv[4],strlen(a->argv[4]))) {
2783 print_line = -1;
2784 } else {
2785 print_line = 0;
2786 }
2787 }
2788
2789 if (print_line) {
2790 ast_cli(a->fd, FORMAT, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid),
2792 peer->dynamic ? "(D)" : "(S)", dundi_sockaddr_port(&peer->addr), model2str(peer->model), avgms, status);
2793 }
2794 }
2795 ast_cli(a->fd, "%d dundi peers [%d online, %d offline, %d unmonitored]\n", total_peers, online_peers, offline_peers, unmonitored_peers);
2797 return CLI_SUCCESS;
2798#undef FORMAT
2799#undef FORMAT2
2800}
jack_status_t status
Definition: app_jack.c:146
static char * dundi_sockaddr_stringify_host(const struct ast_sockaddr *addr)
Definition: pbx_dundi.c:2607

References a, dundi_peer::addr, ast_cli(), ast_eid_to_str(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_sockaddr_isnull(), dundi_peer::avgms, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dundi_sockaddr_port(), dundi_sockaddr_stringify_host(), dundi_peer::dynamic, dundi_peer::eid, FORMAT, FORMAT2, dundi_peer::lastms, dundi_peer::list, dundi_peer::maxms, dundi_peer::model, model2str(), NULL, status, and ast_cli_entry::usage.

◆ dundi_show_precache()

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

Definition at line 2923 of file pbx_dundi.c.

2924{
2925#define FORMAT2 "%-12.12s %-12.12s %-10.10s\n"
2926#define FORMAT "%-12.12s %-12.12s %02d:%02d:%02d\n"
2927 struct dundi_precache_queue *qe;
2928 int h,m,s;
2929 time_t now;
2930 switch (cmd) {
2931 case CLI_INIT:
2932 e->command = "dundi show precache";
2933 e->usage =
2934 "Usage: dundi show precache\n"
2935 " Lists all known DUNDi scheduled precache updates.\n";
2936 return NULL;
2937 case CLI_GENERATE:
2938 return NULL;
2939 }
2940 if (a->argc != 3) {
2941 return CLI_SHOWUSAGE;
2942 }
2943 time(&now);
2944 ast_cli(a->fd, FORMAT2, "Number", "Context", "Expiration");
2946 AST_LIST_TRAVERSE(&pcq, qe, list) {
2947 s = qe->expiration - now;
2948 h = s / 3600;
2949 s = s % 3600;
2950 m = s / 60;
2951 s = s % 60;
2952 ast_cli(a->fd, FORMAT, qe->number, qe->context, h,m,s);
2953 }
2955
2956 return CLI_SUCCESS;
2957#undef FORMAT
2958#undef FORMAT2
2959}
struct dundi_precache_queue::@412 list
Definition: pbx_dundi.c:344

References a, ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dundi_precache_queue::context, dundi_precache_queue::expiration, FORMAT, FORMAT2, dundi_precache_queue::list, NULL, dundi_precache_queue::number, and ast_cli_entry::usage.

◆ dundi_show_requests()

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

Definition at line 2856 of file pbx_dundi.c.

2857{
2858#define FORMAT2 "%-15s %-15s %-15s %-3.3s %-3.3s\n"
2859#define FORMAT "%-15s %-15s %-15s %-3.3d %-3.3d\n"
2860 struct dundi_request *req;
2861 char eidstr[20];
2862 switch (cmd) {
2863 case CLI_INIT:
2864 e->command = "dundi show requests";
2865 e->usage =
2866 "Usage: dundi show requests\n"
2867 " Lists all known pending DUNDi requests.\n";
2868 return NULL;
2869 case CLI_GENERATE:
2870 return NULL;
2871 }
2872 if (a->argc != 3) {
2873 return CLI_SHOWUSAGE;
2874 }
2876 ast_cli(a->fd, FORMAT2, "Number", "Context", "Root", "Max", "Rsp");
2878 ast_cli(a->fd, FORMAT, req->number, req->dcontext,
2879 dundi_eid_zero(&req->root_eid) ? "<unspecified>" : ast_eid_to_str(eidstr, sizeof(eidstr), &req->root_eid), req->maxcount, req->respcount);
2880 }
2882 return CLI_SUCCESS;
2883#undef FORMAT
2884#undef FORMAT2
2885}

References a, ast_cli(), ast_eid_to_str(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dundi_request::dcontext, dundi_eid_zero(), FORMAT, FORMAT2, dundi_request::list, dundi_request::maxcount, NULL, dundi_request::number, dundi_request::respcount, dundi_request::root_eid, and ast_cli_entry::usage.

◆ dundi_show_trans()

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

Definition at line 2802 of file pbx_dundi.c.

2803{
2804#define FORMAT2 "%-47s %-5.5s %-5.5s %-3.3s %-3.3s %-3.3s\n"
2805#define FORMAT "%-41s:%5d %-5.5d %-5.5d %-3.3d %-3.3d %-3.3d\n"
2806 struct dundi_transaction *trans;
2807 switch (cmd) {
2808 case CLI_INIT:
2809 e->command = "dundi show trans";
2810 e->usage =
2811 "Usage: dundi show trans\n"
2812 " Lists all known DUNDi transactions.\n";
2813 return NULL;
2814 case CLI_GENERATE:
2815 return NULL;
2816 }
2817 if (a->argc != 3) {
2818 return CLI_SHOWUSAGE;
2819 }
2821 ast_cli(a->fd, FORMAT2, "Remote", "Src", "Dst", "Tx", "Rx", "Ack");
2822 AST_LIST_TRAVERSE(&alltrans, trans, all) {
2824 ast_sockaddr_port(&trans->addr), trans->strans, trans->dtrans,
2825 trans->oseqno, trans->iseqno, trans->aseqno);
2826 }
2828 return CLI_SUCCESS;
2829#undef FORMAT
2830#undef FORMAT2
2831}
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
Definition: netsock2.h:517

References a, dundi_transaction::addr, dundi_transaction::all, dundi_transaction::aseqno, ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_sockaddr_port, ast_sockaddr_stringify_host(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dundi_transaction::dtrans, FORMAT, FORMAT2, dundi_transaction::iseqno, NULL, dundi_transaction::oseqno, dundi_transaction::strans, and ast_cli_entry::usage.

◆ dundi_sockaddr_port()

static uint16_t dundi_sockaddr_port ( const struct ast_sockaddr addr)
static

Definition at line 2615 of file pbx_dundi.c.

2616{
2617 /*
2618 * Test to avoid a debug message complaining about addr
2619 * not being an IPv4 or IPv6 address.
2620 */
2621 if (ast_sockaddr_isnull(addr)) {
2622 return 0;
2623 }
2624 return ast_sockaddr_port(addr);
2625}

References ast_sockaddr_isnull(), and ast_sockaddr_port.

Referenced by dundi_show_peer(), and dundi_show_peers().

◆ dundi_sockaddr_stringify_host()

static char * dundi_sockaddr_stringify_host ( const struct ast_sockaddr addr)
static

Definition at line 2607 of file pbx_dundi.c.

2608{
2609 if (ast_sockaddr_isnull(addr)) {
2610 return "(Unspecified)";
2611 }
2612 return ast_sockaddr_stringify_host(addr);
2613}

References ast_sockaddr_isnull(), and ast_sockaddr_stringify_host().

Referenced by dundi_show_peers().

◆ dundi_store_history()

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

Definition at line 2336 of file pbx_dundi.c.

2337{
2338 switch (cmd) {
2339 case CLI_INIT:
2340 e->command = "dundi store history {on|off}";
2341 e->usage =
2342 "Usage: dundi store history {on|off}\n"
2343 " Enables/Disables storing of DUNDi requests and times for debugging\n"
2344 "purposes\n";
2345 return NULL;
2346 case CLI_GENERATE:
2347 return NULL;
2348 }
2349
2350 if (a->argc != e->args) {
2351 return CLI_SHOWUSAGE;
2352 }
2353 if (!strncasecmp(a->argv[e->args -1], "on", 2)) {
2355 ast_cli(a->fd, "DUNDi History Storage Enabled\n");
2356 } else {
2358 ast_cli(a->fd, "DUNDi History Storage Disabled\n");
2359 }
2360 return CLI_SUCCESS;
2361}

References a, ast_cli_entry::args, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, global_storehistory, NULL, and ast_cli_entry::usage.

◆ dundi_xmit()

static int dundi_xmit ( struct dundi_packet pack)
static

Definition at line 3175 of file pbx_dundi.c.

3176{
3177 int res;
3178 if (dundidebug)
3179 dundi_showframe(pack->h, 0, &pack->parent->addr, pack->datalen - sizeof(struct dundi_hdr));
3180
3181 if (netsocket2 < 0) {
3182 res = ast_sendto(netsocket, pack->data, pack->datalen, 0, &pack->parent->addr);
3183 } else {
3184 if (ast_sockaddr_is_ipv4(&pack->parent->addr)) {
3185 res = ast_sendto(netsocket, pack->data, pack->datalen, 0, &pack->parent->addr);
3186 } else {
3187 res = ast_sendto(netsocket2, pack->data, pack->datalen, 0, &pack->parent->addr);
3188 }
3189 }
3190
3191 if (res < 0) {
3192 ast_log(LOG_WARNING, "Failed to transmit to '%s': %s\n",
3193 ast_sockaddr_stringify(&pack->parent->addr), strerror(errno));
3194 }
3195 if (res > 0)
3196 res = 0;
3197 return res;
3198}
ssize_t ast_sendto(int sockfd, const void *buf, size_t len, int flags, const struct ast_sockaddr *dest_addr)
Wrapper around sendto(2) that uses ast_sockaddr.
Definition: netsock2.c:614
int ast_sockaddr_is_ipv4(const struct ast_sockaddr *addr)
Determine if the address is an IPv4 address.
Definition: netsock2.c:497
static int netsocket
Definition: pbx_dundi.c:186
static int netsocket2
Definition: pbx_dundi.c:187

References dundi_transaction::addr, ast_log, ast_sendto(), ast_sockaddr_is_ipv4(), ast_sockaddr_stringify(), dundi_packet::data, dundi_packet::datalen, dundi_showframe(), dundidebug, errno, dundi_packet::h, LOG_WARNING, netsocket, netsocket2, and dundi_packet::parent.

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

◆ dundifunc_read()

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

Definition at line 4143 of file pbx_dundi.c.

4144{
4145 int results;
4146 int x;
4147 struct dundi_result dr[MAX_RESULTS];
4152 );
4153 char *parse;
4154 struct ast_flags opts = { 0, };
4155
4156 buf[0] = '\0';
4157
4158 if (ast_strlen_zero(num)) {
4159 ast_log(LOG_WARNING, "DUNDILOOKUP requires an argument (number)\n");
4160 return -1;
4161 }
4162
4163 parse = ast_strdupa(num);
4164
4166
4167 if (!ast_strlen_zero(args.options)) {
4169 }
4170 if (ast_strlen_zero(args.context)) {
4171 args.context = "e164";
4172 }
4173
4174 results = dundi_lookup(dr, MAX_RESULTS, NULL, args.context, args.number, ast_test_flag(&opts, OPT_BYPASS_CACHE));
4175 if (results > 0) {
4176 sort_results(dr, results);
4177 for (x = 0; x < results; x++) {
4179 snprintf(buf, len, "%s/%s", dr[x].tech, dr[x].dest);
4180 break;
4181 }
4182 }
4183 }
4184
4185 return 0;
4186}

References args, AST_APP_ARG, ast_app_parse_options(), AST_DECLARE_APP_ARGS, ast_log, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_test_flag, buf, voicemailpwcheck::context, dr, DUNDI_FLAG_EXISTS, dundi_lookup(), dundi_query_opts, len(), LOG_WARNING, MAX_RESULTS, NULL, OPT_BYPASS_CACHE, options, and sort_results().

◆ encrypt_memcpy()

static int encrypt_memcpy ( unsigned char *  dst,
unsigned char *  src,
int  len,
unsigned char *  iv,
ast_aes_encrypt_key ecx 
)
static

Definition at line 1379 of file pbx_dundi.c.

1380{
1381 unsigned char curblock[16];
1382 int x;
1383 memcpy(curblock, iv, sizeof(curblock));
1384 while(len > 0) {
1385 for (x=0;x<16;x++)
1386 curblock[x] ^= src[x];
1387 ast_aes_encrypt(curblock, dst, ecx);
1388 memcpy(curblock, dst, sizeof(curblock));
1389 dst += 16;
1390 src += 16;
1391 len -= 16;
1392 }
1393 return 0;
1394}
int ast_aes_encrypt(const unsigned char *in, unsigned char *out, const ast_aes_encrypt_key *key)
AES encrypt data.
Definition: res_crypto.c:749

References ast_aes_encrypt(), and len().

Referenced by dundi_encrypt().

◆ find_peer()

static struct dundi_peer * find_peer ( dundi_eid eid)
static

Definition at line 521 of file pbx_dundi.c.

522{
523 struct dundi_peer *cur = NULL;
524
525 if (!eid)
526 eid = &empty_eid;
527
529 if (!ast_eid_cmp(&cur->eid,eid))
530 break;
531 }
532
533 if (!cur && any_peer)
534 cur = any_peer;
535
536 return cur;
537}
static struct dundi_peer * any_peer
Wildcard peer.
Definition: pbx_dundi.c:354

References any_peer, ast_eid_cmp(), AST_LIST_TRAVERSE, dundi_peer::eid, empty_eid, dundi_peer::list, and NULL.

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

◆ find_transaction()

static struct dundi_transaction * find_transaction ( struct dundi_hdr hdr,
struct ast_sockaddr sin 
)
static

Definition at line 418 of file pbx_dundi.c.

419{
420 struct dundi_transaction *trans;
421
422 /* Look for an exact match first */
423 AST_LIST_TRAVERSE(&alltrans, trans, all) {
424 if (!ast_sockaddr_cmp(&trans->addr, sin) &&
425 ((trans->strans == (ntohs(hdr->dtrans) & 32767)) /* Matches our destination */ ||
426 ((trans->dtrans == (ntohs(hdr->strans) & 32767)) && (!hdr->dtrans))) /* We match their destination */) {
427 if (hdr->strans) {
428 trans->dtrans = ntohs(hdr->strans) & 32767;
429 }
430 return trans;
431 }
432 }
433
434 switch(hdr->cmdresp & 0x7f) {
441 if (!hdr->strans)
442 break;
443 /* Create new transaction */
444 if (!(trans = create_transaction(NULL)))
445 break;
446 ast_sockaddr_copy(&trans->addr, sin);
447 trans->dtrans = ntohs(hdr->strans) & 32767;
448 default:
449 break;
450 }
451
452 return trans;
453}
#define DUNDI_COMMAND_NULL
Definition: dundi.h:170
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares two ast_sockaddr structures.
Definition: netsock2.c:388

References dundi_transaction::addr, dundi_transaction::all, AST_LIST_TRAVERSE, ast_sockaddr_cmp(), ast_sockaddr_copy(), dundi_hdr::cmdresp, create_transaction(), dundi_hdr::dtrans, dundi_transaction::dtrans, DUNDI_COMMAND_DPDISCOVER, DUNDI_COMMAND_EIDQUERY, DUNDI_COMMAND_ENCRYPT, DUNDI_COMMAND_NULL, DUNDI_COMMAND_PRECACHERQ, DUNDI_COMMAND_REGREQ, NULL, dundi_hdr::strans, and dundi_transaction::strans.

Referenced by handle_frame().

◆ get_ipaddress()

static int get_ipaddress ( char *  ip,
size_t  size,
const char *  str,
int  family 
)
static

Definition at line 4895 of file pbx_dundi.c.

4896{
4897 struct ast_sockaddr *addrs;
4898
4899 if (!ast_sockaddr_resolve(&addrs, str, 0, family)) {
4900 return -1;
4901 }
4902
4903 ast_copy_string(ip, ast_sockaddr_stringify_host(&addrs[0]), size);
4904 ast_free(addrs);
4905
4906 return 0;
4907}
const char * str
Definition: app_jack.c:147

References ast_copy_string(), ast_free, ast_sockaddr_resolve(), ast_sockaddr_stringify_host(), and str.

Referenced by set_config(), and set_host_ipaddr().

◆ get_mapping_weight()

static int get_mapping_weight ( struct dundi_mapping map,
struct varshead headp 
)
static

Definition at line 565 of file pbx_dundi.c.

566{
567 char buf[32];
568
569 buf[0] = 0;
570 if (map->weightstr) {
571 if (headp) {
572 pbx_substitute_variables_varshead(headp, map->weightstr, buf, sizeof(buf) - 1);
573 } else {
575 }
576
577 if (sscanf(buf, "%30d", &map->_weight) != 1)
578 map->_weight = MAX_WEIGHT;
579 }
580
581 return map->_weight;
582}
void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
Definition: ael_main.c:211

References dundi_mapping::_weight, buf, MAX_WEIGHT, NULL, pbx_substitute_variables_helper(), pbx_substitute_variables_varshead(), and dundi_mapping::weightstr.

Referenced by dundi_lookup_local(), and dundi_show_mappings().

◆ get_trans_id()

static int get_trans_id ( void  )
static

Definition at line 486 of file pbx_dundi.c.

487{
488 struct dundi_transaction *t;
489 int stid = (ast_random() % 32766) + 1;
490 int tid = stid;
491
492 do {
494 if (t->strans == tid)
495 break;
496 }
497 if (!t)
498 return tid;
499 tid = (tid % 32766) + 1;
500 } while (tid != stid);
501
502 return 0;
503}

References dundi_transaction::all, AST_LIST_TRAVERSE, ast_random(), and dundi_transaction::strans.

Referenced by create_transaction(), and reset_transaction().

◆ handle_command_response()

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

Definition at line 1592 of file pbx_dundi.c.

1593{
1594 /* Handle canonical command / response */
1595 int final = hdr->cmdresp & 0x80;
1596 int cmd = hdr->cmdresp & 0x7f;
1597 int x,y,z;
1598 int resp;
1599 int res;
1600 int authpass=0;
1601 unsigned char *bufcpy;
1602#ifdef LOW_MEMORY
1603 struct dundi_ie_data *ied = ast_calloc(1, sizeof(*ied));
1604#else
1605 struct dundi_ie_data _ied = {
1606 .pos = 0,
1607 };
1608 struct dundi_ie_data *ied = &_ied;
1609#endif
1610 struct dundi_ies ies = {
1611 .eidcount = 0,
1612 };
1613 struct dundi_peer *peer = NULL;
1614 char eid_str[20];
1615 char eid_str2[20];
1616 int retval = -1;
1617
1618 if (!ied) {
1619 return -1;
1620 }
1621
1622 if (datalen) {
1623 bufcpy = ast_alloca(datalen);
1624 /* Make a copy for parsing */
1625 memcpy(bufcpy, hdr->ies, datalen);
1626 ast_debug(1, "Got canonical message %d (%d), %d bytes data%s\n", cmd, hdr->oseqno, datalen, final ? " (Final)" : "");
1627 if (dundi_parse_ies(&ies, bufcpy, datalen) < 0) {
1628 ast_log(LOG_WARNING, "Failed to parse DUNDI information elements!\n");
1629 goto return_cleanup;
1630 }
1631 }
1632 switch(cmd) {
1636 if (cmd == DUNDI_COMMAND_EIDQUERY)
1638 else if (cmd == DUNDI_COMMAND_PRECACHERQ)
1640 else
1642 /* A dialplan or entity discover -- qualify by highest level entity */
1643 peer = find_peer(ies.eids[0]);
1644 if (!peer) {
1646 dundi_send(trans, resp, 0, 1, ied);
1647 } else {
1648 int hasauth = 0;
1649 trans->us_eid = peer->us_eid;
1650 if (strlen(peer->inkey)) {
1651 hasauth = encrypted;
1652 } else
1653 hasauth = 1;
1654 if (hasauth) {
1655 /* Okay we're authentiated and all, now we check if they're authorized */
1656 if (!ies.called_context)
1657 ies.called_context = "e164";
1658 if (cmd == DUNDI_COMMAND_EIDQUERY) {
1659 res = dundi_answer_entity(trans, &ies, ies.called_context);
1660 } else {
1661 if (ast_strlen_zero(ies.called_number)) {
1662 /* They're not permitted to access that context */
1663 dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Invalid or missing number/entity");
1664 dundi_send(trans, resp, 0, 1, ied);
1665 } else if ((cmd == DUNDI_COMMAND_DPDISCOVER) &&
1666 (peer->model & DUNDI_MODEL_INBOUND) &&
1667 has_permission(&peer->permit, ies.called_context)) {
1668 res = dundi_answer_query(trans, &ies, ies.called_context);
1669 if (res < 0) {
1670 /* There is no such dundi context */
1671 dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Unsupported DUNDI Context");
1672 dundi_send(trans, resp, 0, 1, ied);
1673 }
1674 } else if ((cmd = DUNDI_COMMAND_PRECACHERQ) &&
1675 (peer->pcmodel & DUNDI_MODEL_INBOUND) &&
1676 has_permission(&peer->include, ies.called_context)) {
1677 res = dundi_prop_precache(trans, &ies, ies.called_context);
1678 if (res < 0) {
1679 /* There is no such dundi context */
1680 dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Unsupported DUNDI Context");
1681 dundi_send(trans, resp, 0, 1, ied);
1682 }
1683 } else {
1684 /* They're not permitted to access that context */
1685 dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Permission to context denied");
1686 dundi_send(trans, resp, 0, 1, ied);
1687 }
1688 }
1689 } else {
1690 /* They're not permitted to access that context */
1691 dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Unencrypted responses not permitted");
1692 dundi_send(trans, resp, 0, 1, ied);
1693 }
1694 }
1695 break;
1697 /* A register request -- should only have one entity */
1698 peer = find_peer(ies.eids[0]);
1699
1700 /* if the peer is not found and we have a valid 'any_peer' setting */
1701 if (any_peer && peer == any_peer) {
1702 /* copy any_peer into a new peer object */
1703 peer = ast_calloc(1, sizeof(*peer));
1704 if (peer) {
1705 deep_copy_peer(peer, any_peer);
1706
1707 /* set EID to remote EID */
1708 peer->eid = *ies.eids[0];
1709
1713 }
1714 }
1715
1716 if (!peer || !peer->dynamic) {
1718 dundi_send(trans, DUNDI_COMMAND_REGRESPONSE, 0, 1, ied);
1719 } else {
1720 int hasauth = 0;
1721 trans->us_eid = peer->us_eid;
1722 if (!ast_strlen_zero(peer->inkey)) {
1723 hasauth = encrypted;
1724 } else
1725 hasauth = 1;
1726 if (hasauth) {
1727 int expire = default_expiration;
1728 char data[256];
1729 int needqual = 0;
1731 peer->registerexpire = ast_sched_add(sched, (expire + 10) * 1000, do_register_expire, peer);
1732 snprintf(data, sizeof(data), "%s:%d", ast_sockaddr_stringify(&trans->addr), expire);
1733 ast_db_put("dundi/dpeers", dundi_eid_to_str_short(eid_str, sizeof(eid_str), &peer->eid), data);
1734 if (ast_sockaddr_cmp(&peer->addr, &trans->addr)) {
1735 ast_verb(3, "Registered DUNDi peer '%s' at '%s'\n",
1736 ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid),
1737 ast_sockaddr_stringify(&trans->addr));
1738 needqual = 1;
1739 }
1740
1741 ast_sockaddr_copy(&peer->addr, &trans->addr);
1743 dundi_send(trans, DUNDI_COMMAND_REGRESPONSE, 0, 1, ied);
1744 if (needqual)
1745 qualify_peer(peer, 1);
1746 }
1747 }
1748 break;
1750 /* A dialplan response, lets see what we got... */
1751 if (ies.cause < 1) {
1752 /* Success of some sort */
1753 ast_debug(1, "Looks like success of some sort (%d), %d answers\n", ies.cause, ies.anscount);
1754 if (ast_test_flag(trans, FLAG_ENCRYPT)) {
1755 authpass = encrypted;
1756 } else
1757 authpass = 1;
1758 if (authpass) {
1759 /* Pass back up answers */
1760 if (trans->parent && trans->parent->dr) {
1761 y = trans->parent->respcount;
1762 for (x=0;x<ies.anscount;x++) {
1763 if (trans->parent->respcount < trans->parent->maxcount) {
1764 /* Make sure it's not already there */
1765 for (z=0;z<trans->parent->respcount;z++) {
1766 if ((trans->parent->dr[z].techint == ies.answers[x]->protocol) &&
1767 !strcmp(trans->parent->dr[z].dest, (char *)ies.answers[x]->data))
1768 break;
1769 }
1770 if (z == trans->parent->respcount) {
1771 /* Copy into parent responses */
1772 trans->parent->dr[trans->parent->respcount].flags = ntohs(ies.answers[x]->flags);
1773 trans->parent->dr[trans->parent->respcount].techint = ies.answers[x]->protocol;
1774 trans->parent->dr[trans->parent->respcount].weight = ntohs(ies.answers[x]->weight);
1775 trans->parent->dr[trans->parent->respcount].eid = ies.answers[x]->eid;
1776 if (ies.expiration > 0)
1777 trans->parent->dr[trans->parent->respcount].expiration = ies.expiration;
1778 else
1781 sizeof(trans->parent->dr[trans->parent->respcount].eid_str),
1782 &ies.answers[x]->eid);
1783 ast_copy_string(trans->parent->dr[trans->parent->respcount].dest, (char *)ies.answers[x]->data,
1784 sizeof(trans->parent->dr[trans->parent->respcount].dest));
1786 sizeof(trans->parent->dr[trans->parent->respcount].tech));
1787 trans->parent->respcount++;
1789 } else if (trans->parent->dr[z].weight > ntohs(ies.answers[x]->weight)) {
1790 /* Update weight if appropriate */
1791 trans->parent->dr[z].weight = ntohs(ies.answers[x]->weight);
1792 }
1793 } else
1794 ast_log(LOG_NOTICE, "Dropping excessive answers to request for %s@%s\n",
1795 trans->parent->number, trans->parent->dcontext);
1796 }
1797 /* Save all the results (if any) we had. Even if no results, still cache lookup. Let
1798 the cache know if this request was unaffected by our entity list. */
1799 cache_save(&trans->them_eid, trans->parent, y,
1800 ies.hint ? ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_UNAFFECTED)) : 0, ies.expiration, 0);
1801 if (ies.hint) {
1802 cache_save_hint(&trans->them_eid, trans->parent, ies.hint, ies.expiration);
1806 if (strlen((char *)ies.hint->data) > strlen(trans->parent->hmd->exten)) {
1807 ast_copy_string(trans->parent->hmd->exten, (char *)ies.hint->data,
1808 sizeof(trans->parent->hmd->exten));
1809 }
1810 } else {
1812 }
1813 }
1814 if (ies.expiration > 0) {
1815 if (trans->parent->expiration > ies.expiration) {
1816 trans->parent->expiration = ies.expiration;
1817 }
1818 }
1819 }
1820 /* Close connection if not final */
1821 if (!final)
1822 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
1823 }
1824
1825 } else {
1826 /* Auth failure, check for data */
1827 if (!final) {
1828 /* Cancel if they didn't already */
1829 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
1830 }
1831 }
1832 break;
1834 /* A dialplan response, lets see what we got... */
1835 if (ies.cause < 1) {
1836 /* Success of some sort */
1837 ast_debug(1, "Looks like success of some sort (%d)\n", ies.cause);
1838 if (ast_test_flag(trans, FLAG_ENCRYPT)) {
1839 authpass = encrypted;
1840 } else
1841 authpass = 1;
1842 if (authpass) {
1843 /* Pass back up answers */
1844 if (trans->parent && trans->parent->dei && ies.q_org) {
1845 if (!trans->parent->respcount) {
1846 trans->parent->respcount++;
1847 if (ies.q_dept)
1848 ast_copy_string(trans->parent->dei->orgunit, ies.q_dept, sizeof(trans->parent->dei->orgunit));
1849 if (ies.q_org)
1850 ast_copy_string(trans->parent->dei->org, ies.q_org, sizeof(trans->parent->dei->org));
1851 if (ies.q_locality)
1852 ast_copy_string(trans->parent->dei->locality, ies.q_locality, sizeof(trans->parent->dei->locality));
1853 if (ies.q_stateprov)
1854 ast_copy_string(trans->parent->dei->stateprov, ies.q_stateprov, sizeof(trans->parent->dei->stateprov));
1855 if (ies.q_country)
1856 ast_copy_string(trans->parent->dei->country, ies.q_country, sizeof(trans->parent->dei->country));
1857 if (ies.q_email)
1858 ast_copy_string(trans->parent->dei->email, ies.q_email, sizeof(trans->parent->dei->email));
1859 if (ies.q_phone)
1860 ast_copy_string(trans->parent->dei->phone, ies.q_phone, sizeof(trans->parent->dei->phone));
1861 if (ies.q_ipaddr)
1862 ast_copy_string(trans->parent->dei->ipaddr, ies.q_ipaddr, sizeof(trans->parent->dei->ipaddr));
1863 if (!ast_eid_cmp(&trans->them_eid, &trans->parent->query_eid)) {
1864 /* If it's them, update our address */
1865 ast_copy_string(trans->parent->dei->ipaddr, ast_sockaddr_stringify_addr(&trans->addr), sizeof(trans->parent->dei->ipaddr));
1866 }
1867 }
1868 if (ies.hint) {
1871 }
1872 }
1873 /* Close connection if not final */
1874 if (!final)
1875 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
1876 }
1877
1878 } else {
1879 /* Auth failure, check for data */
1880 if (!final) {
1881 /* Cancel if they didn't already */
1882 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
1883 }
1884 }
1885 break;
1887 /* A dialplan response, lets see what we got... */
1888 if (ies.cause < 1) {
1889 int hasauth;
1890 /* Success of some sort */
1891 if (ast_test_flag(trans, FLAG_ENCRYPT)) {
1892 hasauth = encrypted;
1893 } else
1894 hasauth = 1;
1895
1896 if (!hasauth) {
1897 ast_log(LOG_NOTICE, "Reponse to register not authorized!\n");
1898 if (!final) {
1899 dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Improper signature in answer");
1900 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, ied);
1901 }
1902 } else {
1903 ast_debug(1, "Yay, we've registered as '%s' to '%s'\n", ast_eid_to_str(eid_str, sizeof(eid_str), &trans->us_eid),
1904 ast_eid_to_str(eid_str2, sizeof(eid_str2), &trans->them_eid));
1905 /* Close connection if not final */
1906 if (!final)
1907 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
1908 }
1909 } else {
1910 /* Auth failure, cancel if they didn't for some reason */
1911 if (!final) {
1912 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
1913 }
1914 }
1915 break;
1917 case DUNDI_COMMAND_NULL:
1919 /* Do nothing special */
1920 if (!final)
1921 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
1922 break;
1924 if ((ast_test_flag(trans, FLAG_SENDFULLKEY)) || AST_LIST_EMPTY(&trans->lasttrans) || !(peer = find_peer(&trans->them_eid))) {
1925 /* No really, it's over at this point */
1926 if (!final)
1927 dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
1928 } else {
1929 /* Send with full key */
1931 if (final) {
1932 /* Ooops, we got a final message, start by sending ACK... */
1933 dundi_ack(trans, hdr->cmdresp & 0x80);
1934 trans->aseqno = trans->iseqno;
1935 /* Now, we gotta create a new transaction */
1936 if (!reset_transaction(trans)) {
1937 /* Make sure handle_frame doesn't destroy us */
1938 hdr->cmdresp &= 0x7f;
1939 /* Parse the message we transmitted */
1940 memset(&ies, 0, sizeof(ies));
1941 dundi_parse_ies(&ies, (AST_LIST_FIRST(&trans->lasttrans))->h->ies, (AST_LIST_FIRST(&trans->lasttrans))->datalen - sizeof(struct dundi_hdr));
1942 /* Reconstruct outgoing encrypted packet */
1943 memset(ied, 0, sizeof(*ied));
1946 dundi_ie_append_raw(ied, DUNDI_IE_SIGNATURE, peer->txenckey + 128, 128);
1947 if (ies.encblock)
1949 dundi_send(trans, DUNDI_COMMAND_ENCRYPT, 0, (AST_LIST_FIRST(&trans->lasttrans))->h->cmdresp & 0x80, ied);
1950 peer->sentfullkey = 1;
1951 }
1952 }
1953 }
1954 break;
1956 if (!encrypted) {
1957 /* No nested encryption! */
1958 if ((trans->iseqno == 1) && !trans->oseqno) {
1959 if (!ies.eids[0] || !(peer = find_peer(ies.eids[0])) ||
1960 ((!ies.encsharedkey || !ies.encsig) && !ies.keycrc32) ||
1961 (check_key(peer, ies.encsharedkey, ies.encsig, ies.keycrc32) < 1)) {
1962 if (!final) {
1963 dundi_send(trans, DUNDI_COMMAND_ENCREJ, 0, 1, NULL);
1964 }
1965 break;
1966 }
1967 apply_peer(trans, peer);
1968 /* Key passed, use new contexts for this session */
1969 trans->ecx = peer->them_ecx;
1970 trans->dcx = peer->them_dcx;
1971 }
1972 if (ast_test_flag(trans, FLAG_ENCRYPT) && ies.encblock && ies.enclen) {
1973 struct dundi_hdr *dhdr;
1974 unsigned char decoded[MAX_PACKET_SIZE];
1975 int ddatalen;
1976 ddatalen = sizeof(decoded);
1977 dhdr = dundi_decrypt(trans, decoded, &ddatalen, hdr, ies.encblock, ies.enclen);
1978 if (dhdr) {
1979 /* Handle decrypted response */
1980 if (dundidebug)
1981 dundi_showframe(dhdr, 3, &trans->addr, ddatalen - sizeof(struct dundi_hdr));
1982 handle_command_response(trans, dhdr, ddatalen - sizeof(struct dundi_hdr), 1);
1983 /* Carry back final flag */
1984 hdr->cmdresp |= dhdr->cmdresp & 0x80;
1985 break;
1986 } else {
1987 ast_debug(1, "Ouch, decrypt failed :(\n");
1988 }
1989 }
1990 }
1991 if (!final) {
1992 /* Turn off encryption */
1994 dundi_send(trans, DUNDI_COMMAND_ENCREJ, 0, 1, NULL);
1995 }
1996 break;
1997 default:
1998 /* Send unknown command if we don't know it, with final flag IFF it's the
1999 first command in the dialog and only if we haven't received final notification */
2000 if (!final) {
2002 dundi_send(trans, DUNDI_COMMAND_UNKNOWN, 0, !hdr->oseqno, ied);
2003 }
2004 }
2005
2006 retval = 0;
2007
2008return_cleanup:
2009#ifdef LOW_MEMORY
2010 ast_free(ied);
2011#endif
2012 return retval;
2013}
int dundi_ie_append_byte(struct dundi_ie_data *ied, unsigned char ie, unsigned char dat)
Definition: dundi-parser.c:617
int dundi_parse_ies(struct dundi_ies *ies, unsigned char *data, int datalen)
Definition: dundi-parser.c:637
#define DUNDI_COMMAND_ENCREJ
Definition: dundi.h:175
#define DUNDI_IE_UNKNOWN
Definition: dundi.h:192
#define DUNDI_COMMAND_UNKNOWN
Definition: dundi.h:169
@ DUNDI_CAUSE_NOAUTH
Definition: dundi.h:125
static ENTRY retval
Definition: hsearch.c:50
#define ast_verb(level,...)
static char * ast_sockaddr_stringify_addr(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only.
Definition: netsock2.h:286
static int reset_transaction(struct dundi_transaction *trans)
Definition: pbx_dundi.c:505
static int dundi_answer_query(struct dundi_transaction *trans, struct dundi_ies *ies, char *ccontext)
Definition: pbx_dundi.c:1093
static int handle_command_response(struct dundi_transaction *trans, struct dundi_hdr *hdr, int datalen, int encrypted)
Definition: pbx_dundi.c:1592
static int dundi_prop_precache(struct dundi_transaction *trans, struct dundi_ies *ies, char *ccontext)
Definition: pbx_dundi.c:946
static int do_register_expire(const void *data)
Definition: pbx_dundi.c:1327
static int check_key(struct dundi_peer *peer, unsigned char *newkey, unsigned char *newsig, uint32_t keycrc32)
Definition: pbx_dundi.c:1498
static int dundi_ack(struct dundi_transaction *trans, int final)
Definition: pbx_dundi.c:457
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)
Definition: pbx_dundi.c:1412
#define MAX_PACKET_SIZE
Definition: pbx_dundi.c:155
static void deep_copy_peer(struct dundi_peer *peer_dst, const struct dundi_peer *peer_src)
Definition: pbx_dundi.c:1551
static int dundi_answer_entity(struct dundi_transaction *trans, struct dundi_ies *ies, char *ccontext)
Definition: pbx_dundi.c:815
char country[80]
Definition: dundi.h:239
char phone[80]
Definition: dundi.h:245
char orgunit[80]
Definition: dundi.h:243
char locality[80]
Definition: dundi.h:241
char email[80]
Definition: dundi.h:244
char ipaddr[80]
Definition: dundi.h:246
char stateprov[80]
Definition: dundi.h:240
char org[80]
Definition: dundi.h:242
char * q_org
Definition: dundi-parser.h:38
char * q_country
Definition: dundi-parser.h:41
char * q_phone
Definition: dundi-parser.h:43
char * q_locality
Definition: dundi-parser.h:39
char * q_ipaddr
Definition: dundi-parser.h:44
unsigned long keycrc32
Definition: dundi-parser.h:48
unsigned char * encsharedkey
Definition: dundi-parser.h:46
char * q_email
Definition: dundi-parser.h:42
unsigned char * encsig
Definition: dundi-parser.h:47
char * q_dept
Definition: dundi-parser.h:37
char * q_stateprov
Definition: dundi-parser.h:40
struct dundi_encblock * encblock
Definition: dundi-parser.h:49
struct dundi_entity_info * dei
Definition: pbx_dundi.c:281

References dundi_transaction::addr, dundi_peer::addr, dundi_ies::anscount, dundi_ies::answers, any_peer, apply_peer(), dundi_transaction::aseqno, ast_alloca, ast_calloc, ast_clear_flag, ast_clear_flag_nonstd, ast_copy_string(), ast_db_put(), ast_debug, ast_eid_cmp(), ast_eid_to_str(), ast_free, AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log, ast_sched_add(), AST_SCHED_DEL, ast_set_flag, ast_set_flag_nonstd, ast_sockaddr_cmp(), ast_sockaddr_copy(), ast_sockaddr_stringify(), ast_sockaddr_stringify_addr(), ast_strlen_zero(), ast_test_flag, ast_test_flag_nonstd, ast_verb, cache_save(), cache_save_hint(), dundi_ies::called_context, dundi_ies::called_number, dundi_ies::cause, check_key(), dundi_hdr::cmdresp, dundi_entity_info::country, dundi_answer::data, dundi_hint::data, dundi_request::dcontext, dundi_transaction::dcx, deep_copy_peer(), default_expiration, dundi_request::dei, dundi_result::dest, do_register_expire(), dundi_request::dr, dundi_ack(), dundi_answer_entity(), dundi_answer_query(), dundi_cache_time, DUNDI_CAUSE_GENERAL, DUNDI_CAUSE_NOAUTH, DUNDI_COMMAND_CANCEL, DUNDI_COMMAND_DPDISCOVER, DUNDI_COMMAND_DPRESPONSE, DUNDI_COMMAND_EIDQUERY, DUNDI_COMMAND_EIDRESPONSE, DUNDI_COMMAND_ENCREJ, DUNDI_COMMAND_ENCRYPT, DUNDI_COMMAND_INVALID, DUNDI_COMMAND_NULL, DUNDI_COMMAND_PRECACHERP, DUNDI_COMMAND_PRECACHERQ, DUNDI_COMMAND_REGREQ, DUNDI_COMMAND_REGRESPONSE, DUNDI_COMMAND_UNKNOWN, dundi_decrypt(), dundi_eid_to_str_short(), DUNDI_HINT_DONT_ASK, DUNDI_HINT_TTL_EXPIRED, DUNDI_HINT_UNAFFECTED, dundi_ie_append_byte(), dundi_ie_append_cause(), dundi_ie_append_eid(), dundi_ie_append_encdata(), dundi_ie_append_raw(), dundi_ie_append_short(), DUNDI_IE_CAUSE, DUNDI_IE_EID, DUNDI_IE_ENCDATA, DUNDI_IE_EXPIRATION, DUNDI_IE_SHAREDKEY, DUNDI_IE_SIGNATURE, DUNDI_IE_UNKNOWN, DUNDI_MODEL_INBOUND, dundi_parse_ies(), dundi_prop_precache(), dundi_send(), dundi_showframe(), dundidebug, dundi_peer::dynamic, dundi_transaction::ecx, dundi_answer::eid, dundi_result::eid, dundi_peer::eid, dundi_result::eid_str, dundi_ies::eidcount, dundi_ies::eids, dundi_entity_info::email, dundi_ies::encblock, dundi_encblock::encdata, dundi_ies::enclen, dundi_ies::encsharedkey, dundi_ies::encsig, dundi_result::expiration, dundi_ies::expiration, dundi_request::expiration, dundi_hint_metadata::exten, find_peer(), FLAG_ENCRYPT, FLAG_SENDFULLKEY, dundi_answer::flags, dundi_result::flags, handle_command_response(), has_permission(), dundi_ies::hint, dundi_request::hmd, dundi_hdr::ies, dundi_peer::include, dundi_peer::inkey, dundi_entity_info::ipaddr, dundi_transaction::iseqno, dundi_encblock::iv, dundi_ies::keycrc32, dundi_transaction::lasttrans, dundi_peer::list, dundi_entity_info::locality, LOG_NOTICE, LOG_WARNING, MAX_PACKET_SIZE, dundi_request::maxcount, dundi_peer::model, NULL, dundi_request::number, dundi_entity_info::org, dundi_entity_info::orgunit, dundi_hdr::oseqno, dundi_transaction::oseqno, dundi_transaction::parent, dundi_peer::pcmodel, dundi_peer::permit, dundi_entity_info::phone, dundi_ie_data::pos, dundi_answer::protocol, dundi_ies::q_country, dundi_ies::q_dept, dundi_ies::q_email, dundi_ies::q_ipaddr, dundi_ies::q_locality, dundi_ies::q_org, dundi_ies::q_phone, dundi_ies::q_stateprov, qualify_peer(), dundi_request::query_eid, dundi_peer::registerexpire, reset_transaction(), dundi_request::respcount, retval, dundi_peer::sentfullkey, dundi_entity_info::stateprov, dundi_result::tech, tech2str(), dundi_result::techint, dundi_peer::them_dcx, dundi_peer::them_ecx, dundi_transaction::them_eid, dundi_peer::txenckey, dundi_transaction::us_eid, dundi_peer::us_eid, dundi_answer::weight, and dundi_result::weight.

Referenced by handle_command_response(), and handle_frame().

◆ handle_frame()

static int handle_frame ( struct dundi_hdr h,
struct ast_sockaddr sin,
int  datalen 
)
static

Definition at line 2048 of file pbx_dundi.c.

2049{
2050 struct dundi_transaction *trans;
2051 trans = find_transaction(h, sin);
2052 if (!trans) {
2053 dundi_reject(h, sin);
2054 return 0;
2055 }
2056 /* Got a transaction, see where this header fits in */
2057 if (h->oseqno == trans->iseqno) {
2058 /* Just what we were looking for... Anything but ack increments iseqno */
2059 if (ack_trans(trans, h->iseqno) && ast_test_flag(trans, FLAG_FINAL)) {
2060 /* If final, we're done */
2061 destroy_trans(trans, 0);
2062 return 0;
2063 }
2064 if (h->cmdresp != DUNDI_COMMAND_ACK) {
2065 trans->oiseqno = trans->iseqno;
2066 trans->iseqno++;
2067 handle_command_response(trans, h, datalen, 0);
2068 }
2069 if (trans->aseqno != trans->iseqno) {
2070 dundi_ack(trans, h->cmdresp & 0x80);
2071 trans->aseqno = trans->iseqno;
2072 }
2073 /* Delete any saved last transmissions */
2074 destroy_packets(&trans->lasttrans);
2075 if (h->cmdresp & 0x80) {
2076 /* Final -- destroy now */
2077 destroy_trans(trans, 0);
2078 }
2079 } else if (h->oseqno == trans->oiseqno) {
2080 /* Last incoming sequence number -- send ACK without processing */
2081 dundi_ack(trans, 0);
2082 } else {
2083 /* Out of window -- simply drop */
2084 ast_debug(1, "Dropping packet out of window!\n");
2085 }
2086 return 0;
2087}
static int ack_trans(struct dundi_transaction *trans, int iseqno)
Definition: pbx_dundi.c:2027
static void dundi_reject(struct dundi_hdr *h, struct ast_sockaddr *sin)
Definition: pbx_dundi.c:461
static struct dundi_transaction * find_transaction(struct dundi_hdr *hdr, struct ast_sockaddr *sin)
Definition: pbx_dundi.c:418
unsigned char oiseqno
Definition: pbx_dundi.c:265

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

Referenced by socket_read().

◆ has_permission()

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

Definition at line 369 of file pbx_dundi.c.

370{
371 struct permission *perm;
372 int res = 0;
373
374 AST_LIST_TRAVERSE(permlist, perm, list) {
375 if (!strcasecmp(perm->name, "all") || !strcasecmp(perm->name, cont))
376 res = perm->allow;
377 }
378
379 return res;
380}

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

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

◆ load_module()

static int load_module ( void  )
static

Definition at line 5173 of file pbx_dundi.c.

5174{
5175 struct ast_sockaddr sin;
5176 struct ast_sockaddr sin2;
5177
5180
5181 /* Make a UDP socket */
5184
5185 if (!io || !sched) {
5186 goto declined;
5187 }
5188
5190 ast_sockaddr_setnull(&sin2);
5191
5192 if (set_config("dundi.conf", &sin, 0, &sin2)) {
5193 goto declined;
5194 }
5195
5196 if (!ast_sockaddr_isnull(&sin2)) {
5197 if ((ast_sockaddr_is_ipv4(&sin) == ast_sockaddr_is_ipv4(&sin2)) || (ast_sockaddr_is_ipv6(&sin) == ast_sockaddr_is_ipv6(&sin2))) {
5198 ast_log(LOG_ERROR, "bindaddr & bindaddr2 should be different IP protocols.\n");
5199 goto declined;
5200 }
5201
5202 /*bind netsocket to ipv4, netsocket2 to ipv6 */
5203
5204 netsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
5205 netsocket2 = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);
5206 if (netsocket < 0 || netsocket2 < 0) {
5207 ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno));
5208 goto declined;
5209 }
5210 if (ast_sockaddr_is_ipv4(&sin)) {
5211 if (ast_bind(netsocket, &sin)) {
5212 ast_log(LOG_ERROR, "Unable to bind to %s : %s\n",
5213 ast_sockaddr_stringify(&sin), strerror(errno));
5214 goto declined;
5215 }
5216 if (ast_bind(netsocket2, &sin2)) {
5217 ast_log(LOG_ERROR, "Unable to bind to %s : %s\n",
5218 ast_sockaddr_stringify(&sin2), strerror(errno));
5219 goto declined;
5220 }
5221 } else {
5222 if (ast_bind(netsocket, &sin2)) {
5223 ast_log(LOG_ERROR, "Unable to bind to %s : %s\n",
5224 ast_sockaddr_stringify(&sin2), strerror(errno));
5225 goto declined;
5226 }
5227 if (ast_bind(netsocket2, &sin)) {
5228 ast_log(LOG_ERROR, "Unable to bind to %s : %s\n",
5229 ast_sockaddr_stringify(&sin), strerror(errno));
5230 goto declined;
5231 }
5232 }
5233 ast_set_qos(netsocket, tos, 0, "DUNDi");
5234 ast_set_qos(netsocket2, tos, 0, "DUNDi");
5235 } else {
5236 if (ast_sockaddr_is_ipv6(&sin)) {
5237 netsocket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);
5238 } else {
5239 netsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
5240 }
5241 if (netsocket < 0) {
5242 ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno));
5243 goto declined;
5244 }
5245 if (ast_bind(netsocket, &sin)) {
5246 ast_log(LOG_ERROR, "Unable to bind to %s : %s\n",
5247 ast_sockaddr_stringify(&sin), strerror(errno));
5248 goto declined;
5249 }
5250 ast_set_qos(netsocket, tos, 0, "DUNDi");
5251 }
5252
5253 if (start_network_thread()) {
5254 ast_log(LOG_ERROR, "Unable to start network thread\n");
5255 goto declined;
5256 }
5257
5260 ast_log(LOG_ERROR, "Unable to register DUNDi switch\n");
5264
5265 ast_verb(2, "DUNDi Ready and Listening on %s\n", ast_sockaddr_stringify(&sin));
5266 if (!ast_sockaddr_isnull(&sin2))
5267 ast_verb(2, "DUNDi Ready and Listening on %s\n", ast_sockaddr_stringify(&sin2));
5268
5270
5271declined:
5272 unload_module();
5274}
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
void dundi_set_output(void(*func)(const char *))
Definition: dundi-parser.c:627
void dundi_set_error(void(*func)(const char *))
Definition: dundi-parser.c:632
static struct ast_custom_function dundi_function
Definition: pbx_dundi.c:4192
struct io_context * io_context_create(void)
Creates a context Create a context for I/O operations Basically mallocs an IO structure and sets up s...
Definition: io.c:81
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
Determine if this is an IPv6 address.
Definition: netsock2.c:524
int ast_bind(int sockfd, const struct ast_sockaddr *addr)
Wrapper around bind(2) that uses struct ast_sockaddr.
Definition: netsock2.c:590
int ast_set_qos(int sockfd, int tos, int cos, const char *desc)
Set type of service.
Definition: netsock2.c:621
int ast_register_switch(struct ast_switch *sw)
Register an alternative dialplan switch.
Definition: pbx_switch.c:58
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1558
static struct ast_switch dundi_switch
Definition: pbx_dundi.c:4886
static unsigned int tos
Definition: pbx_dundi.c:191
static struct ast_custom_function dundi_query_function
Definition: pbx_dundi.c:4280
static void dundi_debug_output(const char *data)
Definition: pbx_dundi.c:358
static int set_config(char *config_file, struct ast_sockaddr *sin, int reload, struct ast_sockaddr *sin2)
Definition: pbx_dundi.c:4931
static struct ast_custom_function dundi_result_function
Definition: pbx_dundi.c:4354
static void dundi_error_output(const char *data)
Definition: pbx_dundi.c:364
static struct ast_cli_entry cli_dundi[]
Definition: pbx_dundi.c:3125
static struct io_context * io
Definition: pbx_dundi.c:184
static int unload_module(void)
Definition: pbx_dundi.c:5103
static int start_network_thread(void)
Definition: pbx_dundi.c:2302
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
Definition: sched.c:238

References ARRAY_LEN, ast_bind(), ast_cli_register_multiple, ast_custom_function_register, ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_register_switch(), ast_sched_context_create(), ast_set_qos(), ast_sockaddr_is_ipv4(), ast_sockaddr_is_ipv6(), ast_sockaddr_isnull(), ast_sockaddr_setnull(), ast_sockaddr_stringify(), ast_verb, cli_dundi, dundi_debug_output(), dundi_error_output(), dundi_function, dundi_query_function, dundi_result_function, dundi_set_error(), dundi_set_output(), dundi_switch, errno, io, io_context_create(), LOG_ERROR, netsocket, netsocket2, set_config(), start_network_thread(), tos, and unload_module().

◆ load_password()

static void load_password ( void  )
static

Definition at line 2144 of file pbx_dundi.c.

2145{
2146 char *current=NULL;
2147 char *last=NULL;
2148 char tmp[256];
2149 time_t expired;
2150
2151 ast_db_get(secretpath, "secretexpiry", tmp, sizeof(tmp));
2152 if (!ast_get_time_t(tmp, &expired, 0, NULL)) {
2153 ast_db_get(secretpath, "secret", tmp, sizeof(tmp));
2154 current = strchr(tmp, ';');
2155 if (!current)
2156 current = tmp;
2157 else {
2158 *current = '\0';
2159 current++;
2160 };
2161 if ((time(NULL) - expired) < 0) {
2162 if ((expired - time(NULL)) > DUNDI_SECRET_TIME)
2163 expired = time(NULL) + DUNDI_SECRET_TIME;
2164 } else if ((time(NULL) - (expired + DUNDI_SECRET_TIME)) < 0) {
2165 last = current;
2166 current = NULL;
2167 } else {
2168 last = NULL;
2169 current = NULL;
2170 }
2171 }
2172 if (current) {
2173 /* Current key is still valid, just setup rotation properly */
2175 rotatetime = expired;
2176 } else {
2177 /* Current key is out of date, rotate or eliminate all together */
2180 }
2181}
struct sla_ringing_trunk * last
Definition: app_sla.c:332
size_t current
Definition: main/cli.c:113
#define DUNDI_SECRET_TIME
Definition: pbx_dundi.c:181
static char secretpath[80]
Definition: pbx_dundi.c:208

References ast_copy_string(), ast_db_get(), ast_get_time_t(), build_secret(), current, cursecret, DUNDI_SECRET_TIME, last, NULL, rotatetime, save_secret(), secretpath, and tmp().

Referenced by set_config().

◆ mark_mappings()

static void mark_mappings ( void  )
static

Definition at line 4369 of file pbx_dundi.c.

4370{
4371 struct dundi_mapping *map;
4372
4375 map->dead = 1;
4376 }
4378}

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

Referenced by set_config(), and unload_module().

◆ mark_peers()

static void mark_peers ( void  )
static

Definition at line 4359 of file pbx_dundi.c.

4360{
4361 struct dundi_peer *peer;
4363 AST_LIST_TRAVERSE(&peers, peer, list) {
4364 peer->dead = 1;
4365 }
4367}

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

Referenced by set_config(), and unload_module().

◆ model2str()

static char * model2str ( int  model)
static

Definition at line 2409 of file pbx_dundi.c.

2410{
2411 switch(model) {
2413 return "Inbound";
2415 return "Outbound";
2417 return "Symmetric";
2418 default:
2419 return "Unknown";
2420 }
2421}

References DUNDI_MODEL_INBOUND, DUNDI_MODEL_OUTBOUND, DUNDI_MODEL_SYMMETRIC, and dundi_peer::model.

Referenced by dundi_show_peer(), and dundi_show_peers().

◆ network_thread()

static void * network_thread ( void *  ignore)
static

Definition at line 2200 of file pbx_dundi.c.

2201{
2202 /* Our job is simple: Send queued messages, retrying if necessary. Read frames
2203 from the network, and queue them for delivery to the channels */
2204 int res;
2205 /* Establish I/O callback for socket read */
2206 int *socket_read_id = ast_io_add(io, netsocket, socket_read, AST_IO_IN, &netsocket);
2207 int *socket_read_id2 = NULL;
2208 if (netsocket2 >= 0) {
2209 socket_read_id2 = ast_io_add(io, netsocket2, socket_read, AST_IO_IN, &netsocket2);
2210 }
2211
2212 while (!dundi_shutdown) {
2213 res = ast_sched_wait(sched);
2214 if ((res > 1000) || (res < 0))
2215 res = 1000;
2216 res = ast_io_wait(io, res);
2217 if (res >= 0) {
2221 }
2223 }
2224
2225 ast_io_remove(io, socket_read_id);
2226
2227 if (socket_read_id2) {
2228 ast_io_remove(io, socket_read_id2);
2229 }
2230
2231 return NULL;
2232}
#define AST_IO_IN
Definition: io.h:34
int * ast_io_add(struct io_context *ioc, int fd, ast_io_cb callback, short events, void *data)
Adds an IO context.
Definition: io.c:162
int ast_io_wait(struct io_context *ioc, int howlong)
Waits for IO.
Definition: io.c:278
int ast_io_remove(struct io_context *ioc, int *id)
Removes an IO context.
Definition: io.c:245
static int socket_read(int *id, int fd, short events, void *sock)
Definition: pbx_dundi.c:2089
static void check_password(void)
Definition: pbx_dundi.c:2183
static int dundi_shutdown
Definition: pbx_dundi.c:215
int ast_sched_runq(struct ast_sched_context *con)
Runs the queue.
Definition: sched.c:786
int ast_sched_wait(struct ast_sched_context *con) attribute_warn_unused_result
Determines number of seconds until the next outstanding event to take place.
Definition: sched.c:433

References ast_io_add(), AST_IO_IN, ast_io_remove(), ast_io_wait(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_sched_runq(), ast_sched_wait(), check_password(), dundi_shutdown, io, netsocket, netsocket2, NULL, and socket_read().

Referenced by start_network_thread().

◆ optimize_transactions()

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

Definition at line 3590 of file pbx_dundi.c.

3591{
3592 /* Minimize the message propagation through DUNDi by
3593 alerting the network to hops which should be not be considered */
3594 struct dundi_transaction *trans;
3595 struct dundi_peer *peer;
3596 dundi_eid tmp;
3597 int x;
3598 int needpush;
3599
3601 AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) {
3602 /* Pop off the true root */
3603 if (trans->eidcount) {
3604 tmp = trans->eids[--trans->eidcount];
3605 needpush = 1;
3606 } else {
3607 tmp = trans->us_eid;
3608 needpush = 0;
3609 }
3610
3611 AST_LIST_TRAVERSE(&peers, peer, list) {
3612 if (ast_eid_cmp(&peer->eid, &empty_eid) && /* peer's eid is not empty (in case of dynamic peers) */
3613 (peer->lastms > -1) && /* peer is reachable */
3614 has_permission(&peer->include, dr->dcontext) && /* peer has destination context */
3615 ast_eid_cmp(&peer->eid, &trans->them_eid) && /* peer is not transaction endpoint */
3616 (peer->order <= order)) {
3617 /* For each other transaction, make sure we don't
3618 ask this EID about the others if they're not
3619 already in the list */
3620 if (!ast_eid_cmp(&tmp, &peer->eid))
3621 x = -1;
3622 else {
3623 for (x=0;x<trans->eidcount;x++) {
3624 if (!ast_eid_cmp(&trans->eids[x], &peer->eid))
3625 break;
3626 }
3627 }
3628 if (x == trans->eidcount) {
3629 /* Nope not in the list, if needed, add us at the end since we're the source */
3630 if (trans->eidcount < DUNDI_MAX_STACK - needpush) {
3631 trans->eids[trans->eidcount++] = peer->eid;
3632 /* Need to insert the real root (or us) at the bottom now as
3633 a requirement now. */
3634 needpush = 1;
3635 }
3636 }
3637 }
3638 }
3639 /* If necessary, push the true root back on the end */
3640 if (needpush)
3641 trans->eids[trans->eidcount++] = tmp;
3642 }
3644
3645 return 0;
3646}

References ast_eid_cmp(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, dr, DUNDI_MAX_STACK, dundi_peer::eid, dundi_transaction::eidcount, dundi_transaction::eids, empty_eid, has_permission(), dundi_peer::include, dundi_peer::lastms, dundi_peer::list, order, dundi_peer::order, dundi_transaction::them_eid, tmp(), and dundi_transaction::us_eid.

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

◆ populate_addr()

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

Definition at line 4594 of file pbx_dundi.c.

4595{
4596 char data[256];
4597 char *c;
4598 int port, expire;
4599 char eid_str[20];
4600 ast_eid_to_str(eid_str, sizeof(eid_str), eid);
4601 if (!ast_db_get("dundi/dpeers", eid_str, data, sizeof(data))) {
4602 /*
4603 * data is in the form:
4604 * IPv6 address: [ffff:ffff::ffff:ffff]:port:expire
4605 * IPv4 address: a.b.c.d:port:expire
4606 */
4607 c = data;
4608 if (*c == '[') {
4609 /* Need to skip over the IPv6 address. */
4610 c = strchr(c, ']');
4611 }
4612 if (c) {
4613 c = strchr(c, ':');
4614 }
4615 if (c) {
4616 *c = '\0';
4617 c++;
4618 if (sscanf(c, "%5d:%30d", &port, &expire) == 2) {
4619 /* Got it! */
4620 struct ast_sockaddr *addrs;
4621
4622 if (ast_sockaddr_resolve(&addrs, data, PARSE_PORT_FORBID, AF_UNSPEC) > 0){
4623 ast_sockaddr_copy(&peer->addr, &addrs[0]);
4624 ast_free(addrs);
4625 }
4626 ast_sockaddr_set_port(&peer->addr, port);
4627 peer->registerexpire = ast_sched_add(sched, (expire + 10) * 1000, do_register_expire, peer);
4628 }
4629 }
4630 }
4631}
static struct test_val c

References dundi_peer::addr, ast_db_get(), ast_eid_to_str(), ast_free, ast_sched_add(), ast_sockaddr_copy(), ast_sockaddr_resolve(), ast_sockaddr_set_port, c, do_register_expire(), dundi_peer::eid, PARSE_PORT_FORBID, and dundi_peer::registerexpire.

Referenced by build_peer().

◆ precache_trans()

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

Definition at line 3443 of file pbx_dundi.c.

3444{
3445 struct dundi_ie_data ied;
3446 int x, res;
3447 int max = 999999;
3448 int expiration = dundi_cache_time;
3449 int ouranswers=0;
3450 dundi_eid *avoid[1] = { NULL, };
3451 int direct[1] = { 0, };
3452 struct dundi_result dr[MAX_RESULTS];
3453 struct dundi_hint_metadata hmd;
3454 if (!trans->parent) {
3455 ast_log(LOG_WARNING, "Tried to discover a transaction with no parent?!?\n");
3456 return -1;
3457 }
3458 memset(&hmd, 0, sizeof(hmd));
3459 memset(&dr, 0, sizeof(dr));
3460 /* Look up the answers we're going to include */
3461 for (x=0;x<mapcount;x++)
3462 ouranswers = dundi_lookup_local(dr, maps + x, trans->parent->number, &trans->us_eid, ouranswers, &hmd);
3463 if (ouranswers < 0)
3464 ouranswers = 0;
3465 for (x=0;x<ouranswers;x++) {
3466 if (dr[x].weight < max)
3467 max = dr[x].weight;
3468 }
3469 if (max) {
3470 /* If we do not have a canonical result, keep looking */
3471 res = dundi_lookup_internal(dr + ouranswers, MAX_RESULTS - ouranswers, NULL, trans->parent->dcontext, trans->parent->number, trans->ttl, 1, &hmd, &expiration, 0, 1, &trans->them_eid, avoid, direct);
3472 if (res > 0) {
3473 /* Append answer in result */
3474 ouranswers += res;
3475 }
3476 }
3477
3478 if (ouranswers > 0) {
3479 *foundanswers += ouranswers;
3480 memset(&ied, 0, sizeof(ied));
3482 if (!dundi_eid_zero(&trans->us_eid))
3483 dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid);
3484 for (x=0;x<trans->eidcount;x++)
3485 dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->eids[x]);
3488 dundi_ie_append_short(&ied, DUNDI_IE_TTL, trans->ttl);
3489 for (x=0;x<ouranswers;x++) {
3490 /* Add answers */
3491 if (dr[x].expiration && (expiration > dr[x].expiration))
3492 expiration = dr[x].expiration;
3493 dundi_ie_append_answer(&ied, DUNDI_IE_ANSWER, &dr[x].eid, dr[x].techint, dr[x].flags, dr[x].weight, dr[x].dest);
3494 }
3495 dundi_ie_append_hint(&ied, DUNDI_IE_HINT, hmd.flags, hmd.exten);
3496 dundi_ie_append_short(&ied, DUNDI_IE_EXPIRATION, expiration);
3497 if (trans->autokilltimeout)
3498 trans->autokillid = ast_sched_add(sched, trans->autokilltimeout, do_autokill, trans);
3499 if (expiration < *minexp)
3500 *minexp = expiration;
3501 return dundi_send(trans, DUNDI_COMMAND_PRECACHERQ, 0, 0, &ied);
3502 } else {
3503 /* Oops, nothing to send... */
3504 destroy_trans(trans, 0);
3505 return 0;
3506 }
3507}

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

Referenced by precache_transactions().

◆ precache_transactions()

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

Definition at line 3542 of file pbx_dundi.c.

3543{
3544 struct dundi_transaction *trans;
3545
3546 /* Mark all as "in thread" so they don't disappear */
3548 AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) {
3549 if (trans->thread)
3550 ast_log(LOG_WARNING, "This shouldn't happen, really...\n");
3551 trans->thread = 1;
3552 }
3554
3555 AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) {
3556 if (!ast_test_flag(trans, FLAG_DEAD))
3557 precache_trans(trans, maps, mapcount, expiration, foundanswers);
3558 }
3559
3560 /* Cleanup any that got destroyed in the mean time */
3562 AST_LIST_TRAVERSE_SAFE_BEGIN(&dr->trans, trans, parentlist) {
3563 trans->thread = 0;
3564 if (ast_test_flag(trans, FLAG_DEAD)) {
3565 ast_debug(1, "Our transaction went away!\n");
3566 /* This is going to remove the transaction from the dundi_request's list, as well
3567 * as the global transactions list */
3568 destroy_trans(trans, 0);
3569 }
3570 }
3573
3574 return 0;
3575}
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
static int precache_trans(struct dundi_transaction *trans, struct dundi_mapping *maps, int mapcount, int *minexp, int *foundanswers)
Definition: pbx_dundi.c:3443

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

Referenced by dundi_precache_internal().

◆ process_clearcache()

static void * process_clearcache ( void *  ignore)
static

Definition at line 2234 of file pbx_dundi.c.

2235{
2236 struct ast_db_entry *db_entry, *db_tree;
2237 int striplen = sizeof("/dundi/cache");
2238 time_t now;
2239
2240 while (!dundi_shutdown) {
2241 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
2242
2243 time(&now);
2244
2245 db_entry = db_tree = ast_db_gettree("dundi/cache", NULL);
2246 for (; db_entry; db_entry = db_entry->next) {
2247 time_t expiry;
2248
2249 if (!ast_get_time_t(db_entry->data, &expiry, 0, NULL)) {
2250 if (expiry < now) {
2251 ast_debug(1, "clearing expired DUNDI cache entry: %s\n", db_entry->key);
2252 ast_db_del("dundi/cache", db_entry->key + striplen);
2253 }
2254 }
2255 }
2256 ast_db_freetree(db_tree);
2257
2258 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
2259 pthread_testcancel();
2260 sleep(60);
2261 pthread_testcancel();
2262 }
2263
2264 return NULL;
2265}

References ast_db_del(), ast_db_freetree(), ast_db_gettree(), ast_debug, ast_get_time_t(), ast_db_entry::data, dundi_shutdown, ast_db_entry::key, ast_db_entry::next, and NULL.

Referenced by start_network_thread().

◆ process_precache()

static void * process_precache ( void *  ign)
static

Definition at line 2267 of file pbx_dundi.c.

2268{
2269 struct dundi_precache_queue *qe;
2270 time_t now;
2271 char context[256];
2272 char number[256];
2273 int run;
2274
2275 while (!dundi_shutdown) {
2276 time(&now);
2277 run = 0;
2279 if ((qe = AST_LIST_FIRST(&pcq))) {
2280 if (!qe->expiration) {
2281 /* Gone... Remove... */
2283 ast_free(qe);
2284 } else if (qe->expiration < now) {
2285 /* Process this entry */
2286 qe->expiration = 0;
2287 ast_copy_string(context, qe->context, sizeof(context));
2288 ast_copy_string(number, qe->number, sizeof(number));
2289 run = 1;
2290 }
2291 }
2293 if (run) {
2295 } else
2296 sleep(1);
2297 }
2298
2299 return NULL;
2300}

References ast_copy_string(), ast_free, AST_LIST_FIRST, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, voicemailpwcheck::context, dundi_precache_queue::context, dundi_precache(), dundi_shutdown, dundi_precache_queue::expiration, dundi_precache_queue::list, NULL, and dundi_precache_queue::number.

Referenced by start_network_thread().

◆ prune_mappings()

static void prune_mappings ( void  )
static

Definition at line 4433 of file pbx_dundi.c.

4434{
4435 struct dundi_mapping *map;
4436
4439 if (map->dead) {
4441 destroy_map(map);
4442 }
4443 }
4446}
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557
static void destroy_map(struct dundi_mapping *map)
Definition: pbx_dundi.c:4412

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

Referenced by set_config(), and unload_module().

◆ prune_peers()

static void prune_peers ( void  )
static

Definition at line 4418 of file pbx_dundi.c.

4419{
4420 struct dundi_peer *peer;
4421
4424 if (peer->dead) {
4426 destroy_peer(peer);
4427 }
4428 }
4431}
static void destroy_peer(struct dundi_peer *peer)
Definition: pbx_dundi.c:4388

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

Referenced by set_config(), and unload_module().

◆ qualify_peer()

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

Definition at line 4571 of file pbx_dundi.c.

4572{
4573 int when;
4575 if (peer->qualtrans)
4576 destroy_trans(peer->qualtrans, 0);
4577 peer->qualtrans = NULL;
4578 if (peer->maxms > 0) {
4579 when = 60000;
4580 if (peer->lastms < 0)
4581 when = 10000;
4582 if (schedonly)
4583 when = 5000;
4584 peer->qualifyid = ast_sched_add(sched, when, do_qualify, peer);
4585 if (!schedonly)
4586 peer->qualtrans = create_transaction(peer);
4587 if (peer->qualtrans) {
4588 peer->qualtx = ast_tvnow();
4591 }
4592 }
4593}
static int do_qualify(const void *data)
Definition: pbx_dundi.c:4563

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

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

◆ query_transactions()

static int query_transactions ( struct dundi_request dr)
static

Definition at line 3577 of file pbx_dundi.c.

3578{
3579 struct dundi_transaction *trans;
3580
3582 AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) {
3583 dundi_query(trans);
3584 }
3586
3587 return 0;
3588}
static int dundi_query(struct dundi_transaction *trans)
Definition: pbx_dundi.c:3509

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

Referenced by dundi_query_eid_internal().

◆ register_request()

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

Definition at line 3764 of file pbx_dundi.c.

3765{
3766 struct dundi_request *cur;
3767 int res=0;
3768 char eid_str[20];
3771 ast_debug(1, "Checking '%s@%s' vs '%s@%s'\n", cur->dcontext, cur->number,
3772 dr->dcontext, dr->number);
3773 if (!strcasecmp(cur->dcontext, dr->dcontext) &&
3774 !strcasecmp(cur->number, dr->number) &&
3775 (!ast_eid_cmp(&cur->root_eid, &dr->root_eid) || (cur->crc32 == dr->crc32))) {
3776 ast_debug(1, "Found existing query for '%s@%s' for '%s' crc '%08x'\n",
3777 cur->dcontext, cur->number, ast_eid_to_str(eid_str, sizeof(eid_str), &cur->root_eid), cur->crc32);
3778 *pending = cur;
3779 res = 1;
3780 break;
3781 }
3782 }
3783 if (!res) {
3784 ast_debug(1, "Registering request for '%s@%s' on behalf of '%s' crc '%08x'\n",
3785 dr->number, dr->dcontext, ast_eid_to_str(eid_str, sizeof(eid_str), &dr->root_eid), dr->crc32);
3786 /* Go ahead and link us in since nobody else is searching for this */
3788 *pending = NULL;
3789 }
3791 return res;
3792}

References ast_debug, ast_eid_cmp(), ast_eid_to_str(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, dundi_request::crc32, dundi_request::dcontext, dr, dundi_request::list, NULL, dundi_request::number, and dundi_request::root_eid.

Referenced by dundi_lookup_internal().

◆ reload()

static int reload ( void  )
static

Definition at line 5159 of file pbx_dundi.c.

5160{
5161 struct ast_sockaddr sin;
5162 struct ast_sockaddr sin2;
5163
5165 ast_sockaddr_setnull(&sin2);
5166
5167 if (set_config("dundi.conf", &sin, 1, &sin2))
5169
5171}
@ AST_MODULE_LOAD_FAILURE
Module could not be loaded properly.
Definition: module.h:102

References AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_sockaddr_setnull(), and set_config().

◆ reschedule_precache()

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

Definition at line 3943 of file pbx_dundi.c.

3944{
3945 struct dundi_precache_queue *qe, *prev;
3946
3949 if (!strcmp(number, qe->number) && !strcasecmp(context, qe->context)) {
3951 break;
3952 }
3953 }
3955 if (!qe) {
3956 int len = sizeof(*qe);
3957 int num_len = strlen(number) + 1;
3958 int context_len = strlen(context) + 1;
3959 if (!(qe = ast_calloc(1, len + num_len + context_len))) {
3961 return;
3962 }
3963 strcpy(qe->number, number);
3964 qe->context = qe->number + num_len + 1;
3965 ast_copy_string(qe->context, context, context_len);
3966 }
3967 time(&qe->expiration);
3968 qe->expiration += expiration;
3969 if ((prev = AST_LIST_FIRST(&pcq))) {
3970 while (AST_LIST_NEXT(prev, list) && ((AST_LIST_NEXT(prev, list))->expiration <= qe->expiration))
3971 prev = AST_LIST_NEXT(prev, list);
3972 AST_LIST_INSERT_AFTER(&pcq, prev, qe, list);
3973 } else
3976}
#define AST_LIST_INSERT_AFTER(head, listelm, elm, field)
Inserts a list entry after a given entry.
Definition: linkedlists.h:695

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

Referenced by dundi_precache_full(), and dundi_precache_internal().

◆ rescomp()

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

Definition at line 2445 of file pbx_dundi.c.

2446{
2447 const struct dundi_result *resa, *resb;
2448 resa = a;
2449 resb = b;
2450 if (resa->weight < resb->weight)
2451 return -1;
2452 if (resa->weight > resb->weight)
2453 return 1;
2454 return 0;
2455}
static struct test_val b

References a, b, and dundi_result::weight.

Referenced by sort_results().

◆ reset_transaction()

static int reset_transaction ( struct dundi_transaction trans)
static

Definition at line 505 of file pbx_dundi.c.

506{
507 int tid;
508 tid = get_trans_id();
509 if (tid < 1)
510 return -1;
511 trans->strans = tid;
512 trans->dtrans = 0;
513 trans->iseqno = 0;
514 trans->oiseqno = 0;
515 trans->oseqno = 0;
516 trans->aseqno = 0;
518 return 0;
519}

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

Referenced by handle_command_response().

◆ save_secret()

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

Definition at line 2131 of file pbx_dundi.c.

2132{
2133 char tmp[350];
2134 if (oldkey)
2135 snprintf(tmp, sizeof(tmp), "%s;%s", oldkey, newkey);
2136 else
2137 snprintf(tmp, sizeof(tmp), "%s", newkey);
2139 ast_db_put(secretpath, "secret", tmp);
2140 snprintf(tmp, sizeof(tmp), "%d", (int)rotatetime);
2141 ast_db_put(secretpath, "secretexpiry", tmp);
2142}

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

Referenced by check_password(), and load_password().

◆ set_config()

static int set_config ( char *  config_file,
struct ast_sockaddr sin,
int  reload,
struct ast_sockaddr sin2 
)
static

Definition at line 4931 of file pbx_dundi.c.

4932{
4933 struct ast_config *cfg;
4934 struct ast_variable *v;
4935 char *cat;
4936 int x;
4937 struct ast_flags config_flags = { 0 };
4938 static int last_port = 0;
4939 int port = 0;
4940 int globalpcmodel = 0;
4941 dundi_eid testeid;
4942 char bind_addr[80]={0,};
4943 char bind_addr2[80]={0,};
4944
4945 if (!(cfg = ast_config_load(config_file, config_flags)) || cfg == CONFIG_STATUS_FILEINVALID) {
4946 ast_log(LOG_ERROR, "Unable to load config %s\n", config_file);
4947 return -1;
4948 }
4949
4952 any_peer = NULL;
4953 outgoing_sip_tech = DUNDI_PROTO_PJSIP; /* Default for new versions */
4954
4956
4958 ast_log(LOG_WARNING, "Entity ID is not set.\n");
4959 }
4960 memcpy(&global_eid, &ast_eid_default, sizeof(global_eid));
4961
4963 ast_copy_string(secretpath, "dundi", sizeof(secretpath));
4964 v = ast_variable_browse(cfg, "general");
4965 while(v) {
4966 if (!strcasecmp(v->name, "port")){
4967 port = atoi(v->value);
4968 } else if (!strcasecmp(v->name, "bindaddr")) {
4969 if (get_ipaddress(bind_addr, sizeof(bind_addr), v->value, AF_UNSPEC) == 0) {
4970 if (!ast_sockaddr_parse(sin, bind_addr, 0)) {
4971 ast_log(LOG_WARNING, "Invalid host/IP '%s'\n", v->value);
4972 }
4973 }
4974 } else if (!strcasecmp(v->name, "bindaddr2")) {
4975 if (get_ipaddress(bind_addr2, sizeof(bind_addr2), v->value, AF_UNSPEC) == 0) {
4976 if (!ast_sockaddr_parse(sin2, bind_addr2, 0)) {
4977 ast_log(LOG_WARNING, "Invalid host/IP '%s'\n", v->value);
4978 }
4979 }
4980 } else if (!strcasecmp(v->name, "authdebug")) {
4981 authdebug = ast_true(v->value);
4982 } else if (!strcasecmp(v->name, "ttl")) {
4983 if ((sscanf(v->value, "%30d", &x) == 1) && (x > 0) && (x < DUNDI_DEFAULT_TTL)) {
4984 dundi_ttl = x;
4985 } else {
4986 ast_log(LOG_WARNING, "'%s' is not a valid TTL at line %d, must be number from 1 to %d\n",
4988 }
4989 } else if (!strcasecmp(v->name, "autokill")) {
4990 if (sscanf(v->value, "%30d", &x) == 1) {
4991 if (x >= 0)
4993 else
4994 ast_log(LOG_NOTICE, "Nice try, but autokill has to be >0 or 'yes' or 'no' at line %d\n", v->lineno);
4995 } else if (ast_true(v->value)) {
4997 } else {
4999 }
5000 } else if (!strcasecmp(v->name, "entityid")) {
5001 if (!ast_str_to_eid(&testeid, v->value))
5002 global_eid = testeid;
5003 else
5004 ast_log(LOG_WARNING, "Invalid global endpoint identifier '%s' at line %d\n", v->value, v->lineno);
5005 } else if (!strcasecmp(v->name, "tos")) {
5006 if (ast_str2tos(v->value, &tos))
5007 ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno);
5008 } else if (!strcasecmp(v->name, "department")) {
5009 ast_copy_string(dept, v->value, sizeof(dept));
5010 } else if (!strcasecmp(v->name, "organization")) {
5011 ast_copy_string(org, v->value, sizeof(org));
5012 } else if (!strcasecmp(v->name, "locality")) {
5013 ast_copy_string(locality, v->value, sizeof(locality));
5014 } else if (!strcasecmp(v->name, "stateprov")) {
5016 } else if (!strcasecmp(v->name, "country")) {
5017 ast_copy_string(country, v->value, sizeof(country));
5018 } else if (!strcasecmp(v->name, "email")) {
5019 ast_copy_string(email, v->value, sizeof(email));
5020 } else if (!strcasecmp(v->name, "phone")) {
5021 ast_copy_string(phone, v->value, sizeof(phone));
5022 } else if (!strcasecmp(v->name, "storehistory")) {
5024 } else if (!strcasecmp(v->name, "outgoing_sip_tech")) {
5025 int outgoing_tech = str2tech(v->value);
5026 if (outgoing_tech != DUNDI_PROTO_SIP && outgoing_tech != DUNDI_PROTO_PJSIP) {
5027 ast_log(LOG_WARNING, "outgoing_sip_tech must be SIP or PJSIP\n");
5028 } else {
5029 outgoing_sip_tech = outgoing_tech;
5030 }
5031 } else if (!strcasecmp(v->name, "pjsip_outgoing_endpoint")) {
5033 } else if (!strcasecmp(v->name, "cachetime")) {
5034 if ((sscanf(v->value, "%30d", &x) == 1)) {
5035 dundi_cache_time = x;
5036 } else {
5037 ast_log(LOG_WARNING, "'%s' is not a valid cache time at line %d. Using default value '%d'.\n",
5039 }
5040 }
5041 v = v->next;
5042 }
5043
5044 if (port == 0) {
5045 port = DUNDI_PORT;
5046 }
5047
5048 if (ast_sockaddr_isnull(sin)) {
5049 sprintf(bind_addr, "0.0.0.0:%d", port);
5050 ast_sockaddr_parse(sin, bind_addr, 0);
5051 } else {
5052 ast_sockaddr_set_port(sin, port);
5053 }
5054
5055 if (last_port == 0) {
5056 last_port = port;
5057 } else if (last_port != port) {
5058 ast_log(LOG_WARNING, "change to port ignored until next asterisk re-start\n");
5059 }
5060
5061 set_host_ipaddr(sin);
5062
5063 if (!ast_sockaddr_isnull(sin2)) {
5064 ast_sockaddr_set_port(sin2, port);
5065 }
5066
5068
5069 mark_mappings();
5070 v = ast_variable_browse(cfg, "mappings");
5071 while (v) {
5073 build_mapping(v->name, v->value);
5075 v = v->next;
5076 }
5078
5079 mark_peers();
5080 cat = ast_category_browse(cfg, NULL);
5081 while(cat) {
5082 if (strcasecmp(cat, "general") && strcasecmp(cat, "mappings")) {
5083 /* Entries */
5084 if (!ast_str_to_eid(&testeid, cat))
5085 build_peer(&testeid, ast_variable_browse(cfg, cat), &globalpcmodel);
5086 else if (!strcasecmp(cat, "*")) {
5087 build_peer(&empty_eid, ast_variable_browse(cfg, cat), &globalpcmodel);
5089 } else
5090 ast_log(LOG_NOTICE, "Ignoring invalid EID entry '%s'\n", cat);
5091 }
5092 cat = ast_category_browse(cfg, cat);
5093 }
5094 prune_peers();
5095
5096 ast_config_destroy(cfg);
5097 load_password();
5098 if (globalpcmodel & DUNDI_MODEL_OUTBOUND)
5100 return 0;
5101}
int ast_str2tos(const char *value, unsigned int *tos)
Convert a string to the appropriate TOS value.
Definition: acl.c:966
static const char config_file[]
Definition: cdr_odbc.c:54
#define DUNDI_DEFAULT_TTL
Definition: dundi.h:218
#define DUNDI_DEFAULT_CACHE_TIME
Definition: dundi.h:220
@ DUNDI_PROTO_SIP
Definition: dundi.h:59
#define ast_config_load(filename, flags)
Load a config file.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3326
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
static void load_password(void)
Definition: pbx_dundi.c:2144
static void prune_peers(void)
Definition: pbx_dundi.c:4418
static void mark_mappings(void)
Definition: pbx_dundi.c:4369
static int get_ipaddress(char *ip, size_t size, const char *str, int family)
Definition: pbx_dundi.c:4895
static void set_host_ipaddr(struct ast_sockaddr *sin)
Definition: pbx_dundi.c:4909
static int authdebug
Definition: pbx_dundi.c:193
static void mark_peers(void)
Definition: pbx_dundi.c:4359
static void prune_mappings(void)
Definition: pbx_dundi.c:4433
static void build_peer(dundi_eid *eid, struct ast_variable *v, int *globalpcmode)
Definition: pbx_dundi.c:4634
static void build_mapping(const char *name, const char *value)
Definition: pbx_dundi.c:4463
static void dundi_precache_full(void)
Definition: pbx_dundi.c:3978
Structure for variables, used for configurations and for channel variables.
int ast_eid_is_empty(const struct ast_eid *eid)
Check if EID is empty.
Definition: utils.c:3099
struct ast_eid ast_eid_default
Global EID.
Definition: options.c:93

References any_peer, ast_category_browse(), ast_config_destroy(), ast_config_load, ast_copy_string(), ast_eid_default, ast_eid_is_empty(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log, ast_sockaddr_isnull(), ast_sockaddr_parse(), ast_sockaddr_set_port, ast_str2tos(), ast_str_to_eid(), ast_true(), ast_variable_browse(), authdebug, build_mapping(), build_peer(), config_file, CONFIG_STATUS_FILEINVALID, country, DEFAULT_MAXMS, dept, dundi_cache_time, DUNDI_DEFAULT_CACHE_TIME, DUNDI_DEFAULT_TTL, DUNDI_MODEL_OUTBOUND, DUNDI_PORT, dundi_precache_full(), DUNDI_PROTO_PJSIP, DUNDI_PROTO_SIP, dundi_ttl, email, empty_eid, find_peer(), get_ipaddress(), global_autokilltimeout, global_eid, global_storehistory, ast_variable::lineno, load_password(), locality, LOG_ERROR, LOG_NOTICE, LOG_WARNING, mark_mappings(), mark_peers(), ast_variable::name, ast_variable::next, NULL, org, outgoing_sip_tech, phone, pjsip_outgoing_endpoint, prune_mappings(), prune_peers(), secretpath, set_host_ipaddr(), stateprov, str2tech(), tos, and ast_variable::value.

Referenced by load_module(), and reload().

◆ set_host_ipaddr()

static void set_host_ipaddr ( struct ast_sockaddr sin)
static

Definition at line 4909 of file pbx_dundi.c.

4910{
4911 char hn[MAXHOSTNAMELEN];
4912 struct addrinfo hints;
4913 int family;
4914
4915 memset(&hints, 0, sizeof(hints));
4916
4917 if (ast_sockaddr_is_ipv6(sin)) {
4918 family = AF_INET6;
4919 } else {
4920 family = AF_INET;
4921 }
4922
4923 if (gethostname(hn, sizeof(hn) - 1) < 0) {
4924 ast_log(LOG_WARNING, "Unable to get host name!\n");
4925 return;
4926 }
4927
4928 get_ipaddress(ipaddr, sizeof(ipaddr), hn, family);
4929}
#define MAXHOSTNAMELEN
Definition: network.h:69

References ast_log, ast_sockaddr_is_ipv6(), get_ipaddress(), ipaddr, LOG_WARNING, and MAXHOSTNAMELEN.

Referenced by set_config().

◆ socket_read()

static int socket_read ( int *  id,
int  fd,
short  events,
void *  sock 
)
static

Definition at line 2089 of file pbx_dundi.c.

2090{
2091 struct ast_sockaddr sin;
2092 int res;
2093 struct dundi_hdr *h;
2094 char buf[MAX_PACKET_SIZE];
2095
2096 res = ast_recvfrom(*((int *)sock), buf, sizeof(buf), 0, &sin);
2097 if (res < 0) {
2098 if (errno != ECONNREFUSED)
2099 ast_log(LOG_WARNING, "Error: %s\n", strerror(errno));
2100 return 1;
2101 }
2102 if (res < sizeof(struct dundi_hdr)) {
2103 ast_log(LOG_WARNING, "midget packet received (%d of %d min)\n", res, (int)sizeof(struct dundi_hdr));
2104 return 1;
2105 }
2106 buf[res] = '\0';
2107 h = (struct dundi_hdr *) buf;
2108 if (dundidebug)
2109 dundi_showframe(h, 1, &sin, res - sizeof(struct dundi_hdr));
2111 handle_frame(h, &sin, res - sizeof(struct dundi_hdr));
2113 return 1;
2114}
ssize_t ast_recvfrom(int sockfd, void *buf, size_t len, int flags, struct ast_sockaddr *src_addr)
Wrapper around recvfrom(2) that uses struct ast_sockaddr.
Definition: netsock2.c:606
static int handle_frame(struct dundi_hdr *h, struct ast_sockaddr *sin, int datalen)
Definition: pbx_dundi.c:2048

References AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log, ast_recvfrom(), buf, dundi_showframe(), dundidebug, errno, handle_frame(), LOG_WARNING, and MAX_PACKET_SIZE.

Referenced by network_thread().

◆ sort_results()

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

Definition at line 2457 of file pbx_dundi.c.

2458{
2459 qsort(results, count, sizeof(results[0]), rescomp);
2460}
static int rescomp(const void *a, const void *b)
Definition: pbx_dundi.c:2445

References rescomp().

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

◆ start_network_thread()

static int start_network_thread ( void  )
static

Definition at line 2302 of file pbx_dundi.c.

2303{
2307 return 0;
2308}
static pthread_t precachethreadid
Definition: pbx_dundi.c:189
static pthread_t netthreadid
Definition: pbx_dundi.c:188
static void * network_thread(void *ignore)
Definition: pbx_dundi.c:2200
static void * process_precache(void *ign)
Definition: pbx_dundi.c:2267
static void * process_clearcache(void *ignore)
Definition: pbx_dundi.c:2234
static pthread_t clearcachethreadid
Definition: pbx_dundi.c:190
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:592

References ast_pthread_create_background, clearcachethreadid, netthreadid, network_thread(), NULL, precachethreadid, process_clearcache(), and process_precache().

Referenced by load_module().

◆ str2tech()

static int str2tech ( const char *  str)
static

Definition at line 400 of file pbx_dundi.c.

401{
402 if (!strcasecmp(str, "IAX") || !strcasecmp(str, "IAX2"))
403 return DUNDI_PROTO_IAX;
404 else if (!strcasecmp(str, "SIP"))
405 return DUNDI_PROTO_SIP;
406 else if (!strcasecmp(str, "H323"))
407 return DUNDI_PROTO_H323;
408 else if (!strcasecmp(str, "PJSIP"))
409 return DUNDI_PROTO_PJSIP;
410 else
411 return -1;
412}
@ DUNDI_PROTO_IAX
Definition: dundi.h:57
@ DUNDI_PROTO_H323
Definition: dundi.h:61

References DUNDI_PROTO_H323, DUNDI_PROTO_IAX, DUNDI_PROTO_PJSIP, DUNDI_PROTO_SIP, and str.

Referenced by build_mapping(), and set_config().

◆ tech2str()

static char * tech2str ( int  tech)
static

Definition at line 382 of file pbx_dundi.c.

383{
384 switch(tech) {
385 case DUNDI_PROTO_NONE:
386 return "None";
387 case DUNDI_PROTO_IAX:
388 return "IAX2";
389 case DUNDI_PROTO_SIP:
390 return "SIP";
391 case DUNDI_PROTO_H323:
392 return "H323";
394 return "PJSIP";
395 default:
396 return "Unknown";
397 }
398}
@ DUNDI_PROTO_NONE
Definition: dundi.h:55

References DUNDI_PROTO_H323, DUNDI_PROTO_IAX, DUNDI_PROTO_NONE, DUNDI_PROTO_PJSIP, and DUNDI_PROTO_SIP.

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

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 5103 of file pbx_dundi.c.

5104{
5110
5111 /* Stop all currently running threads */
5112 dundi_shutdown = 1;
5114 pthread_kill(netthreadid, SIGURG);
5115 pthread_join(netthreadid, NULL);
5117 }
5119 pthread_kill(precachethreadid, SIGURG);
5120 pthread_join(precachethreadid, NULL);
5122 }
5124 pthread_cancel(clearcachethreadid);
5125 pthread_join(clearcachethreadid, NULL);
5127 }
5128
5129 if (netsocket >= 0) {
5130 close(netsocket);
5131 }
5132
5133 if (netsocket2 >= 0) {
5134 close(netsocket2);
5135 }
5136
5137 mark_mappings();
5139 mark_peers();
5140 prune_peers();
5141
5142 if (-1 < netsocket) {
5143 close(netsocket);
5144 netsocket = -1;
5145 }
5146 if (io) {
5148 io = NULL;
5149 }
5150
5151 if (sched) {
5153 sched = NULL;
5154 }
5155
5156 return 0;
5157}
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
void io_context_destroy(struct io_context *ioc)
Destroys a context.
Definition: io.c:107
#define AST_PTHREADT_NULL
Definition: lock.h:66
void ast_unregister_switch(struct ast_switch *sw)
Unregister an alternative switch.
Definition: pbx_switch.c:76
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
Definition: sched.c:271

References ARRAY_LEN, ast_cli_unregister_multiple(), ast_custom_function_unregister(), AST_PTHREADT_NULL, ast_sched_context_destroy(), ast_unregister_switch(), clearcachethreadid, cli_dundi, dundi_function, dundi_query_function, dundi_result_function, dundi_shutdown, dundi_switch, io, io_context_destroy(), mark_mappings(), mark_peers(), netsocket, netsocket2, netthreadid, NULL, precachethreadid, prune_mappings(), and prune_peers().

Referenced by load_module().

◆ unregister_request()

static void unregister_request ( struct dundi_request dr)
static

Definition at line 3794 of file pbx_dundi.c.

3795{
3797 AST_LIST_REMOVE(&requests, dr, list);
3799}

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

Referenced by dundi_lookup_internal().

◆ update_key()

static int update_key ( struct dundi_peer peer)
static

Definition at line 1340 of file pbx_dundi.c.

1341{
1342 unsigned char key[16];
1343 struct ast_key *ekey, *skey;
1344 char eid_str[20];
1345 int res;
1346 if (!peer->keyexpire || (peer->keyexpire < time(NULL))) {
1347 build_iv(key);
1348 ast_aes_set_encrypt_key(key, &peer->us_ecx);
1349 ast_aes_set_decrypt_key(key, &peer->us_dcx);
1350 ekey = ast_key_get(peer->inkey, AST_KEY_PUBLIC);
1351 if (!ekey) {
1352 ast_log(LOG_NOTICE, "No such key '%s' for creating RSA encrypted shared key for '%s'!\n",
1353 peer->inkey, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
1354 return -1;
1355 }
1356 skey = ast_key_get(peer->outkey, AST_KEY_PRIVATE);
1357 if (!skey) {
1358 ast_log(LOG_NOTICE, "No such key '%s' for signing RSA encrypted shared key for '%s'!\n",
1359 peer->outkey, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
1360 return -1;
1361 }
1362 if ((res = ast_encrypt_bin(peer->txenckey, key, sizeof(key), ekey)) != 128) {
1363 ast_log(LOG_NOTICE, "Whoa, got a weird encrypt size (%d != %d)!\n", res, 128);
1364 return -1;
1365 }
1366 if ((res = ast_sign_bin(skey, (char *)peer->txenckey, 128, peer->txenckey + 128))) {
1367 ast_log(LOG_NOTICE, "Failed to sign key (%d)!\n", res);
1368 return -1;
1369 }
1370 peer->us_keycrc32 = crc32(0L, peer->txenckey, 128);
1371 peer->sentfullkey = 0;
1372 /* Looks good */
1373 time(&peer->keyexpire);
1374 peer->keyexpire += dundi_key_ttl;
1375 }
1376 return 0;
1377}
int ast_sign_bin(struct ast_key *key, const char *msg, int msglen, unsigned char *dsig)
Sign a message signature using a given private key.
Definition: res_crypto.c:390
int ast_encrypt_bin(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key)
Encrypt a message using a given private key.
Definition: res_crypto.c:549
static int dundi_key_ttl
Definition: pbx_dundi.c:195
time_t keyexpire
Definition: pbx_dundi.c:326

References ast_aes_set_decrypt_key(), ast_aes_set_encrypt_key(), ast_eid_to_str(), ast_encrypt_bin(), ast_key_get(), AST_KEY_PRIVATE, AST_KEY_PUBLIC, ast_log, ast_sign_bin(), build_iv(), dundi_key_ttl, dundi_peer::eid, dundi_peer::inkey, dundi_peer::keyexpire, LOG_NOTICE, NULL, dundi_peer::outkey, dundi_peer::sentfullkey, dundi_peer::txenckey, dundi_peer::us_dcx, dundi_peer::us_ecx, and dundi_peer::us_keycrc32.

Referenced by dundi_encrypt().

Variable Documentation

◆ __mod_info

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

Definition at line 5282 of file pbx_dundi.c.

◆ alltrans

struct alltrans alltrans = { .first = NULL, .last = NULL, }
static

◆ any_peer

struct dundi_peer* any_peer
static

Wildcard peer.

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

Definition at line 354 of file pbx_dundi.c.

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

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 5282 of file pbx_dundi.c.

◆ authdebug

int authdebug = 0
static

Definition at line 193 of file pbx_dundi.c.

Referenced by set_config().

◆ clearcachethreadid

pthread_t clearcachethreadid = AST_PTHREADT_NULL
static

Definition at line 190 of file pbx_dundi.c.

Referenced by start_network_thread(), and unload_module().

◆ cli_dundi

struct ast_cli_entry cli_dundi[]
static

Definition at line 3125 of file pbx_dundi.c.

Referenced by load_module(), and unload_module().

◆ country

char country[80]
static

◆ cursecret

char cursecret[80]
static

Definition at line 209 of file pbx_dundi.c.

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

◆ default_expiration

int default_expiration = 60
static

◆ dept

char dept[80]
static

Definition at line 201 of file pbx_dundi.c.

Referenced by dundi_query_thread(), and set_config().

◆ dundi_cache_time

int dundi_cache_time = DUNDI_DEFAULT_CACHE_TIME
static

◆ dundi_key_ttl

int dundi_key_ttl = DUNDI_DEFAULT_KEY_EXPIRE
static

Definition at line 195 of file pbx_dundi.c.

Referenced by update_key().

◆ dundi_query_function

struct ast_custom_function dundi_query_function
static
Initial value:
= {
.name = "DUNDIQUERY",
}
static int dundi_query_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: pbx_dundi.c:4221

Definition at line 4280 of file pbx_dundi.c.

Referenced by load_module(), and unload_module().

◆ dundi_query_opts

const struct ast_app_option dundi_query_opts[128] = { [ 'b' ] = { .flag = OPT_BYPASS_CACHE }, }
static

Definition at line 4141 of file pbx_dundi.c.

Referenced by dundi_query_read(), and dundifunc_read().

◆ dundi_result_datastore_info

const struct ast_datastore_info dundi_result_datastore_info
static
Initial value:
= {
.type = "DUNDIQUERY",
.destroy = drds_destroy_cb,
}
static void drds_destroy_cb(void *data)
Definition: pbx_dundi.c:4210

Definition at line 4216 of file pbx_dundi.c.

Referenced by dundi_query_read(), and dundi_result_read().

◆ dundi_result_function

struct ast_custom_function dundi_result_function
static
Initial value:
= {
.name = "DUNDIRESULT",
}
static int dundi_result_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: pbx_dundi.c:4285

Definition at line 4354 of file pbx_dundi.c.

Referenced by load_module(), and unload_module().

◆ dundi_result_id

unsigned int dundi_result_id
static

Definition at line 4197 of file pbx_dundi.c.

Referenced by dundi_query_read().

◆ dundi_shutdown

int dundi_shutdown = 0
static

Definition at line 215 of file pbx_dundi.c.

Referenced by network_thread(), process_clearcache(), process_precache(), and unload_module().

◆ dundi_switch

struct ast_switch dundi_switch
static

Definition at line 4886 of file pbx_dundi.c.

Referenced by load_module(), and unload_module().

◆ dundi_ttl

int dundi_ttl = DUNDI_DEFAULT_TTL
static

Definition at line 194 of file pbx_dundi.c.

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

◆ dundidebug

int dundidebug = 0
static

◆ email

char email[80]
static

Definition at line 206 of file pbx_dundi.c.

Referenced by dundi_query_thread(), make_email_file(), sendmail(), and set_config().

◆ empty_eid

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

◆ global_autokilltimeout

int global_autokilltimeout = 0
static

Definition at line 197 of file pbx_dundi.c.

Referenced by apply_peer(), and set_config().

◆ global_eid

dundi_eid global_eid
static

Definition at line 198 of file pbx_dundi.c.

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

◆ global_storehistory

int global_storehistory = 0
static

Definition at line 200 of file pbx_dundi.c.

Referenced by create_transaction(), dundi_store_history(), and set_config().

◆ io

struct io_context* io
static

Definition at line 184 of file pbx_dundi.c.

Referenced by load_module(), network_thread(), and unload_module().

◆ ipaddr

char ipaddr[80]
static

Definition at line 210 of file pbx_dundi.c.

Referenced by dundi_lookup_local(), and set_host_ipaddr().

◆ locality

char locality[80]
static

Definition at line 203 of file pbx_dundi.c.

Referenced by dundi_query_thread(), and set_config().

◆ mappings

struct mappings mappings = { .first = NULL, .last = NULL, }
static

◆ netsocket

int netsocket = -1
static

◆ netsocket2

int netsocket2 = -1
static

Definition at line 187 of file pbx_dundi.c.

Referenced by dundi_xmit(), load_module(), network_thread(), and unload_module().

◆ netthreadid

pthread_t netthreadid = AST_PTHREADT_NULL
static

Definition at line 188 of file pbx_dundi.c.

Referenced by start_network_thread(), and unload_module().

◆ org

char org[80]
static

Definition at line 202 of file pbx_dundi.c.

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

◆ outgoing_sip_tech

int outgoing_sip_tech
static

Definition at line 211 of file pbx_dundi.c.

Referenced by dundi_exec(), and set_config().

◆ pcq

struct pcq pcq = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
static

◆ peers

struct peers peers = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
static

◆ phone

char phone[80]
static

Definition at line 207 of file pbx_dundi.c.

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

◆ pjsip_outgoing_endpoint

char pjsip_outgoing_endpoint[80]
static

Definition at line 212 of file pbx_dundi.c.

Referenced by dundi_exec(), and set_config().

◆ precachethreadid

pthread_t precachethreadid = AST_PTHREADT_NULL
static

Definition at line 189 of file pbx_dundi.c.

Referenced by start_network_thread(), and unload_module().

◆ requests

struct requests requests = { .first = NULL, .last = NULL, }
static

Referenced by ast_aoc_create().

◆ rotatetime

time_t rotatetime
static

Definition at line 213 of file pbx_dundi.c.

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

◆ sched

struct ast_sched_context* sched
static

Definition at line 185 of file pbx_dundi.c.

◆ secretpath

char secretpath[80]
static

Definition at line 208 of file pbx_dundi.c.

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

◆ stateprov

char stateprov[80]
static

Definition at line 204 of file pbx_dundi.c.

Referenced by dundi_query_thread(), and set_config().

◆ tos

unsigned int tos = 0
static

Definition at line 191 of file pbx_dundi.c.

Referenced by load_module(), and set_config().