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

Distributed Universal Number Discovery (DUNDi) More...

#include "asterisk.h"
#include "asterisk/network.h"
#include <sys/ioctl.h>
#include <zlib.h>
#include <signal.h>
#include <pthread.h>
#include <net/if.h>
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/frame.h"
#include "asterisk/cli.h"
#include "asterisk/lock.h"
#include "asterisk/md5.h"
#include "asterisk/dundi.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/utils.h"
#include "asterisk/netsock2.h"
#include "asterisk/crypto.h"
#include "asterisk/astdb.h"
#include "asterisk/acl.h"
#include "asterisk/app.h"
#include "dundi-parser.h"
Include dependency graph for pbx_dundi.c:

Go to the source code of this file.

Data Structures

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

Macros

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

Enumerations

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

Functions

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

Variables

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

Detailed Description

Distributed Universal Number Discovery (DUNDi)

Definition in file pbx_dundi.c.

Macro Definition Documentation

◆ DUNDI_FLAG_INTERNAL_NOPARTIAL

#define DUNDI_FLAG_INTERNAL_NOPARTIAL   (1 << 17)

Definition at line 176 of file pbx_dundi.c.

Referenced by build_mapping(), and dundi_lookup_local().

◆ DUNDI_MODEL_INBOUND

#define DUNDI_MODEL_INBOUND   (1 << 0)

Definition at line 159 of file pbx_dundi.c.

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

◆ DUNDI_MODEL_OUTBOUND

#define DUNDI_MODEL_OUTBOUND   (1 << 1)

Definition at line 160 of file pbx_dundi.c.

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

◆ DUNDI_MODEL_SYMMETRIC

#define DUNDI_MODEL_SYMMETRIC   (DUNDI_MODEL_INBOUND | DUNDI_MODEL_OUTBOUND)

Definition at line 161 of file pbx_dundi.c.

Referenced by build_peer(), and model2str().

◆ DUNDI_SECRET_TIME

#define DUNDI_SECRET_TIME   DUNDI_DEFAULT_CACHE_TIME

Definition at line 181 of file pbx_dundi.c.

Referenced by load_password(), and save_secret().

◆ DUNDI_TIMING_HISTORY

#define DUNDI_TIMING_HISTORY   10

Keep times of last 10 lookups

Definition at line 164 of file pbx_dundi.c.

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

◆ FORMAT [1/7]

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

◆ FORMAT [2/7]

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

◆ FORMAT [3/7]

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

◆ FORMAT [4/7]

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

◆ FORMAT [5/7]

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

◆ FORMAT [6/7]

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

◆ FORMAT [7/7]

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

◆ FORMAT2 [1/7]

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

◆ FORMAT2 [2/7]

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

◆ FORMAT2 [3/7]

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

◆ FORMAT2 [4/7]

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

◆ FORMAT2 [5/7]

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

◆ FORMAT2 [6/7]

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

◆ FORMAT2 [7/7]

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

◆ MAX_OPTS

#define MAX_OPTS   128

Definition at line 4455 of file pbx_dundi.c.

Referenced by build_mapping().

◆ MAX_PACKET_SIZE

#define MAX_PACKET_SIZE   8192

Definition at line 155 of file pbx_dundi.c.

Referenced by handle_command_response(), and socket_read().

◆ MAX_RESULTS

#define MAX_RESULTS   64

Definition at line 153 of file pbx_dundi.c.

Referenced by dundi_precache_internal(), and dundi_prop_precache().

◆ MAX_WEIGHT

#define MAX_WEIGHT   59999

Definition at line 157 of file pbx_dundi.c.

Referenced by build_mapping(), and get_mapping_weight().

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 wiht 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 wiht ECX/DCX */
172  FLAG_SENDFULLKEY = (1 << 5), /*!< Send full key on transaction */
173  FLAG_STOREHIST = (1 << 6), /*!< Record historic performance */
174 };

◆ anonymous enum

anonymous enum
Enumerator
OPT_BYPASS_CACHE 

Definition at line 4129 of file pbx_dundi.c.

4129  {
4130  OPT_BYPASS_CACHE = (1 << 0),
4131 };

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 5278 of file pbx_dundi.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 5278 of file pbx_dundi.c.

◆ abort_request()

static void abort_request ( struct dundi_request dr)
static

Definition at line 3688 of file pbx_dundi.c.

References AST_LIST_FIRST, AST_LIST_LOCK, AST_LIST_UNLOCK, destroy_trans(), and dundi_request::trans.

Referenced by dundi_lookup_internal().

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

◆ ack_trans()

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

Definition at line 2021 of file pbx_dundi.c.

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

Referenced by handle_frame().

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

◆ append_permission()

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

Definition at line 4442 of file pbx_dundi.c.

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

Referenced by build_peer().

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

◆ append_transaction()

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

Definition at line 3642 of file pbx_dundi.c.

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

Referenced by build_transactions().

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

◆ apply_peer()

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

Definition at line 1295 of file pbx_dundi.c.

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

1296 {
1297  if (ast_sockaddr_isnull(&trans->addr)) {
1298  ast_sockaddr_copy(&trans->addr, &p->addr);
1299  }
1300  trans->us_eid = p->us_eid;
1301  trans->them_eid = p->eid;
1302  /* Enable encryption if appropriate */
1303  if (!ast_strlen_zero(p->inkey))
1304  ast_set_flag(trans, FLAG_ENCRYPT);
1305  if (p->maxms) {
1306  trans->autokilltimeout = p->maxms;
1308  if (p->lastms > 1) {
1309  trans->retranstimer = p->lastms * 2;
1310  /* Keep it from being silly */
1311  if (trans->retranstimer < 150)
1312  trans->retranstimer = 150;
1313  }
1316  } else
1318 }
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:171
#define ast_set_flag(p, flag)
Definition: utils.h:70
dundi_eid us_eid
Definition: pbx_dundi.c:250
dundi_eid them_eid
Definition: pbx_dundi.c:251
int lastms
Definition: pbx_dundi.c:335
#define ast_strlen_zero(foo)
Definition: strings.h:52
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized, or having a 0 length.
Definition: netsock2.h:127
#define DUNDI_DEFAULT_RETRANS_TIMER
Definition: dundi.h:215
dundi_eid us_eid
Definition: pbx_dundi.c:308
static int global_autokilltimeout
Definition: pbx_dundi.c:197
dundi_eid eid
Definition: pbx_dundi.c:304
char inkey[80]
Definition: pbx_dundi.c:309
struct ast_sockaddr addr
Definition: pbx_dundi.c:305
struct ast_sockaddr addr
Definition: pbx_dundi.c:246

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 5278 of file pbx_dundi.c.

◆ avoid_crc32()

static unsigned long avoid_crc32 ( dundi_eid avoid[])
static

Definition at line 3809 of file pbx_dundi.c.

References dundi_request::crc32.

Referenced by dundi_lookup_internal().

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

◆ build_iv()

static void build_iv ( unsigned char *  iv)
static

Definition at line 533 of file pbx_dundi.c.

References ast_random().

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

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

◆ build_mapping()

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

Definition at line 4457 of file pbx_dundi.c.

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, permission::list, LOG_WARNING, map, MAX_OPTS, MAX_WEIGHT, dundi_mapping::options, str2tech(), dundi_mapping::tech, and dundi_mapping::weightstr.

Referenced by set_config().

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

◆ build_peer()

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

Definition at line 4628 of file pbx_dundi.c.

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, global_eid, dundi_peer::include, dundi_peer::inkey, ast_variable::lineno, permission::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().

4629 {
4630  struct dundi_peer *peer;
4631  dundi_eid testeid;
4632  int needregister=0;
4633  char eid_str[20];
4634  int port = 0;
4635 
4636  AST_LIST_LOCK(&peers);
4637  AST_LIST_TRAVERSE(&peers, peer, list) {
4638  if (!ast_eid_cmp(&peer->eid, eid)) {
4639  break;
4640  }
4641  }
4642  if (!peer) {
4643  /* Add us into the list */
4644  if (!(peer = ast_calloc(1, sizeof(*peer)))) {
4646  return;
4647  }
4648  peer->registerid = -1;
4649  peer->registerexpire = -1;
4650  peer->qualifyid = -1;
4651  populate_addr(peer, eid);
4652  AST_LIST_INSERT_HEAD(&peers, peer, list);
4653  }
4654  peer->dead = 0;
4655  peer->eid = *eid;
4656  peer->us_eid = global_eid;
4657  destroy_permissions(&peer->permit);
4658  destroy_permissions(&peer->include);
4659  AST_SCHED_DEL(sched, peer->registerid);
4660  for (; v; v = v->next) {
4661  if (!strcasecmp(v->name, "inkey")) {
4662  ast_copy_string(peer->inkey, v->value, sizeof(peer->inkey));
4663  } else if (!strcasecmp(v->name, "outkey")) {
4664  ast_copy_string(peer->outkey, v->value, sizeof(peer->outkey));
4665  } else if (!strcasecmp(v->name, "port")) {
4666  port = atoi(v->value);
4667  } else if (!strcasecmp(v->name, "host")) {
4668  if (!strcasecmp(v->value, "dynamic")) {
4669  peer->dynamic = 1;
4670  } else {
4671  struct ast_sockaddr *addrs;
4672 
4673  if (ast_sockaddr_resolve(&addrs, v->value, PARSE_PORT_FORBID, AF_UNSPEC) > 0) {
4674  ast_sockaddr_copy(&peer->addr, &addrs[0]);
4675  peer->dynamic = 0;
4676  ast_free(addrs);
4677  } else {
4678  ast_log(LOG_WARNING, "Unable to find host '%s' at line %d\n", v->value, v->lineno);
4679  peer->dead = 1;
4680  }
4681  }
4682  } else if (!strcasecmp(v->name, "ustothem")) {
4683  if (!ast_str_to_eid(&testeid, v->value))
4684  peer->us_eid = testeid;
4685  else
4686  ast_log(LOG_WARNING, "'%s' is not a valid DUNDi Entity Identifier at line %d\n", v->value, v->lineno);
4687  } else if (!strcasecmp(v->name, "include")) {
4688  append_permission(&peer->include, v->value, 1);
4689  } else if (!strcasecmp(v->name, "permit")) {
4690  append_permission(&peer->permit, v->value, 1);
4691  } else if (!strcasecmp(v->name, "noinclude")) {
4692  append_permission(&peer->include, v->value, 0);
4693  } else if (!strcasecmp(v->name, "deny")) {
4694  append_permission(&peer->permit, v->value, 0);
4695  } else if (!strcasecmp(v->name, "register")) {
4696  needregister = ast_true(v->value);
4697  } else if (!strcasecmp(v->name, "order")) {
4698  if (!strcasecmp(v->value, "primary"))
4699  peer->order = 0;
4700  else if (!strcasecmp(v->value, "secondary"))
4701  peer->order = 1;
4702  else if (!strcasecmp(v->value, "tertiary"))
4703  peer->order = 2;
4704  else if (!strcasecmp(v->value, "quartiary"))
4705  peer->order = 3;
4706  else {
4707  ast_log(LOG_WARNING, "'%s' is not a valid order, should be primary, secondary, tertiary or quartiary at line %d\n", v->value, v->lineno);
4708  }
4709  } else if (!strcasecmp(v->name, "qualify")) {
4710  if (!strcasecmp(v->value, "no")) {
4711  peer->maxms = 0;
4712  } else if (!strcasecmp(v->value, "yes")) {
4713  peer->maxms = DEFAULT_MAXMS;
4714  } else if (sscanf(v->value, "%30d", &peer->maxms) != 1) {
4715  ast_log(LOG_WARNING, "Qualification of peer '%s' should be 'yes', 'no', or a number of milliseconds at line %d of dundi.conf\n",
4716  ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), v->lineno);
4717  peer->maxms = 0;
4718  }
4719  } else if (!strcasecmp(v->name, "model")) {
4720  if (!strcasecmp(v->value, "inbound"))
4721  peer->model = DUNDI_MODEL_INBOUND;
4722  else if (!strcasecmp(v->value, "outbound"))
4723  peer->model = DUNDI_MODEL_OUTBOUND;
4724  else if (!strcasecmp(v->value, "symmetric"))
4725  peer->model = DUNDI_MODEL_SYMMETRIC;
4726  else if (!strcasecmp(v->value, "none"))
4727  peer->model = 0;
4728  else {
4729  ast_log(LOG_WARNING, "Unknown model '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n",
4730  v->value, v->lineno);
4731  }
4732  } else if (!strcasecmp(v->name, "precache")) {
4733  if (!strcasecmp(v->value, "inbound"))
4734  peer->pcmodel = DUNDI_MODEL_INBOUND;
4735  else if (!strcasecmp(v->value, "outbound"))
4736  peer->pcmodel = DUNDI_MODEL_OUTBOUND;
4737  else if (!strcasecmp(v->value, "symmetric"))
4739  else if (!strcasecmp(v->value, "none"))
4740  peer->pcmodel = 0;
4741  else {
4742  ast_log(LOG_WARNING, "Unknown pcmodel '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n",
4743  v->value, v->lineno);
4744  }
4745  }
4746  }
4747 
4748  if (!ast_sockaddr_isnull(&peer->addr)) {
4749  ast_sockaddr_set_port(&peer->addr, (0 < port) ? port : DUNDI_PORT);
4750  }
4751 
4752  (*globalpcmode) |= peer->pcmodel;
4753  if (!peer->model && !peer->pcmodel) {
4754  ast_log(LOG_WARNING, "Peer '%s' lacks a model or pcmodel, discarding!\n",
4755  ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
4756  peer->dead = 1;
4757  } else if ((peer->model & DUNDI_MODEL_INBOUND) && (peer->pcmodel & DUNDI_MODEL_OUTBOUND)) {
4758  ast_log(LOG_WARNING, "Peer '%s' may not be both inbound/symmetric model and outbound/symmetric precache model, discarding!\n",
4759  ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
4760  peer->dead = 1;
4761  } else if ((peer->model & DUNDI_MODEL_OUTBOUND) && (peer->pcmodel & DUNDI_MODEL_INBOUND)) {
4762  ast_log(LOG_WARNING, "Peer '%s' may not be both outbound/symmetric model and inbound/symmetric precache model, discarding!\n",
4763  ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
4764  peer->dead = 1;
4765  } else if (!AST_LIST_EMPTY(&peer->include) && !(peer->model & DUNDI_MODEL_OUTBOUND) && !(peer->pcmodel & DUNDI_MODEL_INBOUND)) {
4766  ast_log(LOG_WARNING, "Peer '%s' is supposed to be included in outbound searches but isn't an outbound peer or inbound precache!\n",
4767  ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
4768  } else if (!AST_LIST_EMPTY(&peer->permit) && !(peer->model & DUNDI_MODEL_INBOUND) && !(peer->pcmodel & DUNDI_MODEL_OUTBOUND)) {
4769  ast_log(LOG_WARNING, "Peer '%s' is supposed to have permission for some inbound searches but isn't an inbound peer or outbound precache!\n",
4770  ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
4771  } else {
4772  if (ast_eid_cmp(&peer->eid, &empty_eid)) {
4773  /* Schedule any items for explicitly configured peers. */
4774  if (needregister) {
4775  peer->registerid = ast_sched_add(sched, 2000, do_register, peer);
4776  }
4777  qualify_peer(peer, 1);
4778  }
4779  }
4781 }
struct dundi_peer::@443 list
struct ast_variable * next
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define DUNDI_MODEL_SYMMETRIC
Definition: pbx_dundi.c:161
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
Definition: main/utils.c:2587
static dundi_eid global_eid
Definition: pbx_dundi.c:198
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:171
int qualifyid
Definition: pbx_dundi.c:313
#define DUNDI_PORT
Definition: dundi.h:30
#define LOG_WARNING
Definition: logger.h:274
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static void populate_addr(struct dundi_peer *peer, dundi_eid *eid)
Definition: pbx_dundi.c:4588
Definition: sched.c:76
static void destroy_permissions(struct permissionlist *permlist)
Definition: pbx_dundi.c:4374
int registerexpire
Definition: pbx_dundi.c:325
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
char outkey[80]
Definition: pbx_dundi.c:310
static void qualify_peer(struct dundi_peer *peer, int schedonly)
Definition: pbx_dundi.c:4565
static int do_register(const void *data)
Definition: pbx_dundi.c:4531
Socket address structure.
Definition: netsock2.h:97
An Entity ID is essentially a MAC address, brief and unique.
Definition: utils.h:786
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
Definition: main/utils.c:2842
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized, or having a 0 length.
Definition: netsock2.h:127
int registerid
Definition: pbx_dundi.c:312
#define ast_log
Definition: astobj2.c:42
#define AST_SCHED_DEL(sched, id)
Remove a scheduler entry.
Definition: sched.h:46
#define DUNDI_MODEL_INBOUND
Definition: pbx_dundi.c:159
int ast_str_to_eid(struct ast_eid *eid, const char *s)
Convert a string into an EID.
Definition: main/utils.c:2825
static void append_permission(struct permissionlist *permlist, const char *s, int allow)
Definition: pbx_dundi.c:4442
static dundi_eid empty_eid
Definition: pbx_dundi.c:212
dundi_eid us_eid
Definition: pbx_dundi.c:308
unsigned int dynamic
Definition: pbx_dundi.c:334
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1951
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:537
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
#define DEFAULT_MAXMS
Definition: chan_iax2.c:390
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
dundi_eid eid
Definition: pbx_dundi.c:304
char inkey[80]
Definition: pbx_dundi.c:309
struct dundi_peer::permissionlist permit
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:565
int pcmodel
Definition: pbx_dundi.c:332
struct permissionlist include
Definition: pbx_dundi.c:307
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
struct ast_sockaddr addr
Definition: pbx_dundi.c:305
#define DUNDI_MODEL_OUTBOUND
Definition: pbx_dundi.c:160
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

◆ build_secret()

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

Definition at line 2110 of file pbx_dundi.c.

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

Referenced by check_password(), and load_password().

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

◆ build_transactions()

static void build_transactions ( struct dundi_request dr,
int  ttl,
int  order,
int *  foundcache,
int *  skipped,
int  blockempty,
int  nocache,
int  modeselect,
dundi_eid skip,
dundi_eid avoid[],
int  directs[] 
)
static

Definition at line 3700 of file pbx_dundi.c.

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(), dundi_request::crc32, dundi_request::dcontext, dundi_eid_zero(), DUNDI_HINT_UNAFFECTED, DUNDI_MODEL_OUTBOUND, dundi_peer::eid, dundi_request::expiration, has_permission(), dundi_request::hmd, dundi_peer::include, permission::list, dundi_peer::model, 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().

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

◆ cache_lookup()

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

Definition at line 1242 of file pbx_dundi.c.

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, qualify_peer(), dundi_request::respcount, dundi_request::root_eid, and tmp().

Referenced by build_transactions().

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

◆ cache_lookup_internal()

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

Definition at line 1170 of file pbx_dundi.c.

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, timeout, weight, and dundi_result::weight.

Referenced by cache_lookup().

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

◆ cache_save()

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

Definition at line 899 of file pbx_dundi.c.

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, timeout, and dundi_result::weight.

Referenced by dundi_prop_precache(), and handle_command_response().

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

◆ cache_save_hint()

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

Definition at line 864 of file pbx_dundi.c.

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, dundi_request::root_eid, and timeout.

Referenced by dundi_prop_precache(), and handle_command_response().

865 {
866  int unaffected;
867  char key1[256];
868  char key2[256];
869  char eidpeer_str[20];
870  char eidroot_str[20];
871  char data[80];
872  time_t timeout;
873 
874  if (expiration < 0)
875  expiration = dundi_cache_time;
876 
877  /* Only cache hint if "don't ask" is there... */
878  if (!ast_test_flag_nonstd(hint, htons(DUNDI_HINT_DONT_ASK)))
879  return 0;
880 
881  unaffected = ast_test_flag_nonstd(hint, htons(DUNDI_HINT_UNAFFECTED));
882 
883  dundi_eid_to_str_short(eidpeer_str, sizeof(eidpeer_str), eidpeer);
884  dundi_eid_to_str_short(eidroot_str, sizeof(eidroot_str), &req->root_eid);
885  snprintf(key1, sizeof(key1), "hint/%s/%s/%s/e%08x", eidpeer_str, hint->data, req->dcontext, unaffected ? 0 : req->crc32);
886  snprintf(key2, sizeof(key2), "hint/%s/%s/%s/r%s", eidpeer_str, hint->data, req->dcontext, eidroot_str);
887 
888  time(&timeout);
889  timeout += expiration;
890  snprintf(data, sizeof(data), "%ld|", (long)(timeout));
891 
892  ast_db_put("dundi/cache", key1, data);
893  ast_debug(1, "Caching hint at '%s'\n", key1);
894  ast_db_put("dundi/cache", key2, data);
895  ast_debug(1, "Caching hint at '%s'\n", key2);
896  return 0;
897 }
static int dundi_cache_time
Definition: pbx_dundi.c:196
static int timeout
Definition: cdr_mysql.c:86
char * dundi_eid_to_str_short(char *s, int maxlen, dundi_eid *eid)
Definition: dundi-parser.c:54
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:274
unsigned char data[0]
Definition: dundi.h:112
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
uint32_t crc32
Definition: pbx_dundi.c:286
dundi_eid root_eid
Definition: pbx_dundi.c:277
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: main/db.c:327
#define ast_test_flag_nonstd(p, flag)
Definition: utils.h:173

◆ cancel_request()

static void cancel_request ( struct dundi_request dr)
static

Definition at line 3674 of file pbx_dundi.c.

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

Referenced by dundi_lookup_internal(), and dundi_precache_internal().

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

◆ check_key()

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

Definition at line 1492 of file pbx_dundi.c.

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

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

◆ check_password()

static void check_password ( void  )
static

Definition at line 2177 of file pbx_dundi.c.

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

Referenced by network_thread().

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

◆ check_request()

static int check_request ( struct dundi_request dr)
static

Definition at line 3795 of file pbx_dundi.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and permission::list.

Referenced by dundi_lookup_internal().

3796 {
3797  struct dundi_request *cur;
3798 
3799  AST_LIST_LOCK(&peers);
3800  AST_LIST_TRAVERSE(&requests, cur, list) {
3801  if (cur == dr)
3802  break;
3803  }
3805 
3806  return cur ? 1 : 0;
3807 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct dundi_request::@441 list

◆ complete_peer_helper()

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

Definition at line 2417 of file pbx_dundi.c.

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

Referenced by dundi_show_peer().

2418 {
2419  int which=0, len;
2420  char *ret = NULL;
2421  struct dundi_peer *p;
2422  char eid_str[20];
2423 
2424  if (pos != rpos)
2425  return NULL;
2426  AST_LIST_LOCK(&peers);
2427  len = strlen(word);
2428  AST_LIST_TRAVERSE(&peers, p, list) {
2429  const char *s = ast_eid_to_str(eid_str, sizeof(eid_str), &p->eid);
2430  if (!strncasecmp(word, s, len) && ++which > state) {
2431  ret = ast_strdup(s);
2432  break;
2433  }
2434  }
2436  return ret;
2437 }
struct dundi_peer::@443 list
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
Definition: main/utils.c:2587
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
dundi_eid eid
Definition: pbx_dundi.c:304
short word

◆ create_transaction()

static struct dundi_transaction * create_transaction ( struct dundi_peer p)
static

Definition at line 3137 of file pbx_dundi.c.

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(), NULL, dundi_transaction::retranstimer, dundi_peer::sentfullkey, dundi_transaction::start, and dundi_transaction::strans.

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

3138 {
3139  struct dundi_transaction *trans;
3140  int tid;
3141 
3142  /* Don't allow creation of transactions to non-registered peers */
3143  if (p && ast_sockaddr_isnull(&p->addr)) {
3144  return NULL;
3145  }
3146  tid = get_trans_id();
3147  if (tid < 1)
3148  return NULL;
3149  if (!(trans = ast_calloc(1, sizeof(*trans))))
3150  return NULL;
3151 
3152  if (global_storehistory) {
3153  trans->start = ast_tvnow();
3154  ast_set_flag(trans, FLAG_STOREHIST);
3155  }
3157  trans->autokillid = -1;
3158  if (p) {
3159  apply_peer(trans, p);
3160  if (!p->sentfullkey)
3162  }
3163  trans->strans = tid;
3164  AST_LIST_INSERT_HEAD(&alltrans, trans, all);
3165 
3166  return trans;
3167 }
static void apply_peer(struct dundi_transaction *trans, struct dundi_peer *p)
Definition: pbx_dundi.c:1295
#define ast_set_flag(p, flag)
Definition: utils.h:70
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define NULL
Definition: resample.c:96
struct dundi_transaction::@439 all
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized, or having a 0 length.
Definition: netsock2.h:127
#define DUNDI_DEFAULT_RETRANS_TIMER
Definition: dundi.h:215
static int global_storehistory
Definition: pbx_dundi.c:200
static int get_trans_id(void)
Definition: pbx_dundi.c:480
unsigned short strans
Definition: pbx_dundi.c:260
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
struct ast_sockaddr addr
Definition: pbx_dundi.c:305
struct timeval start
Definition: pbx_dundi.c:247
int sentfullkey
Definition: pbx_dundi.c:314

◆ decrypt_memcpy()

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

Definition at line 1389 of file pbx_dundi.c.

References ast_aes_decrypt().

Referenced by dundi_decrypt().

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

◆ deep_copy_peer()

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

Definition at line 1545 of file pbx_dundi.c.

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

1546 {
1547  struct permission *cur, *perm;
1548 
1549  *peer_dst = *peer_src;
1550  AST_LIST_NEXT(peer_dst, list) = NULL;
1551 
1552  /* Scheduled items cannot go with the copy */
1553  peer_dst->registerid = -1;
1554  peer_dst->qualifyid = -1;
1555  peer_dst->registerexpire = -1;
1556 
1557  /* Transactions and lookup history cannot go with the copy either */
1558  peer_dst->regtrans = NULL;
1559  peer_dst->qualtrans = NULL;
1560  memset(&peer_dst->lookups, 0, sizeof(peer_dst->lookups));
1561 
1562  memset(&peer_dst->permit, 0, sizeof(peer_dst->permit));
1563  memset(&peer_dst->include, 0, sizeof(peer_dst->permit));
1564 
1565  AST_LIST_TRAVERSE(&peer_src->permit, cur, list) {
1566  if (!(perm = ast_calloc(1, sizeof(*perm) + strlen(cur->name) + 1)))
1567  continue;
1568 
1569  perm->allow = cur->allow;
1570  strcpy(perm->name, cur->name);
1571 
1572  AST_LIST_INSERT_HEAD(&peer_dst->permit, perm, list);
1573  }
1574 
1575  AST_LIST_TRAVERSE(&peer_src->include, cur, list) {
1576  if (!(perm = ast_calloc(1, sizeof(*perm) + strlen(cur->name) + 1)))
1577  continue;
1578 
1579  perm->allow = cur->allow;
1580  strcpy(perm->name, cur->name);
1581 
1582  AST_LIST_INSERT_HEAD(&peer_dst->include, perm, list);
1583  }
1584 }
char * lookups[DUNDI_TIMING_HISTORY]
Definition: pbx_dundi.c:327
int qualifyid
Definition: pbx_dundi.c:313
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:438
int registerexpire
Definition: pbx_dundi.c:325
#define NULL
Definition: resample.c:96
int registerid
Definition: pbx_dundi.c:312
struct dundi_transaction * qualtrans
Definition: pbx_dundi.c:330
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
struct dundi_peer::permissionlist permit
char name[0]
Definition: pbx_dundi.c:218
struct permissionlist include
Definition: pbx_dundi.c:307
struct dundi_transaction * regtrans
Definition: pbx_dundi.c:329
struct permission::@435 list

◆ destroy_map()

static void destroy_map ( struct dundi_mapping map)
static

Definition at line 4406 of file pbx_dundi.c.

References ast_free, and dundi_mapping::weightstr.

Referenced by prune_mappings().

4407 {
4408  ast_free(map->weightstr);
4409  ast_free(map);
4410 }
#define ast_free(a)
Definition: astmm.h:182
char * weightstr
Definition: pbx_dundi.c:295

◆ destroy_packet()

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

Definition at line 3194 of file pbx_dundi.c.

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

Referenced by ack_trans(), and handle_command_response().

3195 {
3196  if (pack->parent)
3197  AST_LIST_REMOVE(&pack->parent->packets, pack, list);
3198  AST_SCHED_DEL(sched, pack->retransid);
3199  if (needfree)
3200  ast_free(pack);
3201 }
Definition: sched.c:76
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Definition: linkedlists.h:855
#define AST_SCHED_DEL(sched, id)
Remove a scheduler entry.
Definition: sched.h:46
struct dundi_transaction::packetlist packets
#define ast_free(a)
Definition: astmm.h:182
struct dundi_transaction * parent
Definition: pbx_dundi.c:225
struct permission::@435 list

◆ destroy_packets()

static void destroy_packets ( struct packetlist *  p)
static

Definition at line 2010 of file pbx_dundi.c.

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

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

2011 {
2012  struct dundi_packet *pack;
2013 
2014  while ((pack = AST_LIST_REMOVE_HEAD(p, list))) {
2015  AST_SCHED_DEL(sched, pack->retransid);
2016  ast_free(pack);
2017  }
2018 }
Definition: sched.c:76
#define AST_SCHED_DEL(sched, id)
Remove a scheduler entry.
Definition: sched.h:46
struct dundi_packet::@436 list
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
#define ast_free(a)
Definition: astmm.h:182

◆ destroy_peer()

static void destroy_peer ( struct dundi_peer peer)
static

Definition at line 4382 of file pbx_dundi.c.

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

4383 {
4384  int idx;
4385 
4387  AST_SCHED_DEL(sched, peer->registerid);
4388  if (peer->regtrans) {
4389  destroy_trans(peer->regtrans, 0);
4390  }
4391  AST_SCHED_DEL(sched, peer->qualifyid);
4392  if (peer->qualtrans) {
4393  destroy_trans(peer->qualtrans, 0);
4394  }
4395  destroy_permissions(&peer->permit);
4396  destroy_permissions(&peer->include);
4397 
4398  /* Release lookup history */
4399  for (idx = 0; idx < ARRAY_LEN(peer->lookups); ++idx) {
4400  ast_free(peer->lookups[idx]);
4401  }
4402 
4403  ast_free(peer);
4404 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
char * lookups[DUNDI_TIMING_HISTORY]
Definition: pbx_dundi.c:327
int qualifyid
Definition: pbx_dundi.c:313
Definition: sched.c:76
static void destroy_permissions(struct permissionlist *permlist)
Definition: pbx_dundi.c:4374
int registerexpire
Definition: pbx_dundi.c:325
static void destroy_trans(struct dundi_transaction *trans, int fromtimeout)
Definition: pbx_dundi.c:3203
int registerid
Definition: pbx_dundi.c:312
#define AST_SCHED_DEL(sched, id)
Remove a scheduler entry.
Definition: sched.h:46
struct dundi_transaction * qualtrans
Definition: pbx_dundi.c:330
#define ast_free(a)
Definition: astmm.h:182
struct dundi_peer::permissionlist permit
struct permissionlist include
Definition: pbx_dundi.c:307
struct dundi_transaction * regtrans
Definition: pbx_dundi.c:329

◆ destroy_permissions()

static void destroy_permissions ( struct permissionlist *  permlist)
static

Definition at line 4374 of file pbx_dundi.c.

References ast_free, AST_LIST_REMOVE_HEAD, and permission::list.

Referenced by build_peer(), and destroy_peer().

4375 {
4376  struct permission *perm;
4377 
4378  while ((perm = AST_LIST_REMOVE_HEAD(permlist, list)))
4379  ast_free(perm);
4380 }
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
#define ast_free(a)
Definition: astmm.h:182
struct permission::@435 list

◆ destroy_trans()

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

Definition at line 3203 of file pbx_dundi.c.

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, permission::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_local(), dundi_lookup_thread(), dundi_precache_thread(), dundi_query_thread(), dundi_rexmit(), handle_frame(), precache_trans(), precache_transactions(), and qualify_peer().

3204 {
3205  struct dundi_peer *peer;
3206  int ms;
3207  int x;
3208  int cnt;
3209  char eid_str[20];
3211  AST_LIST_TRAVERSE(&peers, peer, list) {
3212  if (peer->regtrans == trans)
3213  peer->regtrans = NULL;
3214  if (peer->qualtrans == trans) {
3215  if (fromtimeout) {
3216  if (peer->lastms > -1)
3217  ast_log(LOG_NOTICE, "Peer '%s' has become UNREACHABLE!\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
3218  peer->lastms = -1;
3219  } else {
3220  ms = ast_tvdiff_ms(ast_tvnow(), peer->qualtx);
3221  if (ms < 1)
3222  ms = 1;
3223  if (ms < peer->maxms) {
3224  if ((peer->lastms >= peer->maxms) || (peer->lastms < 0))
3225  ast_log(LOG_NOTICE, "Peer '%s' has become REACHABLE!\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
3226  } else if (peer->lastms < peer->maxms) {
3227  ast_log(LOG_NOTICE, "Peer '%s' has become TOO LAGGED (%d ms)\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), ms);
3228  }
3229  peer->lastms = ms;
3230  }
3231  peer->qualtrans = NULL;
3232  }
3233  if (ast_test_flag(trans, FLAG_STOREHIST)) {
3234  if (trans->parent && !ast_strlen_zero(trans->parent->number)) {
3235  if (!ast_eid_cmp(&trans->them_eid, &peer->eid)) {
3236  peer->avgms = 0;
3237  cnt = 0;
3239  for (x=DUNDI_TIMING_HISTORY-1;x>0;x--) {
3240  peer->lookuptimes[x] = peer->lookuptimes[x-1];
3241  peer->lookups[x] = peer->lookups[x-1];
3242  if (peer->lookups[x]) {
3243  peer->avgms += peer->lookuptimes[x];
3244  cnt++;
3245  }
3246  }
3247  peer->lookuptimes[0] = ast_tvdiff_ms(ast_tvnow(), trans->start);
3248  peer->lookups[0] = ast_malloc(strlen(trans->parent->number) + strlen(trans->parent->dcontext) + 2);
3249  if (peer->lookups[0]) {
3250  sprintf(peer->lookups[0], "%s@%s", trans->parent->number, trans->parent->dcontext);
3251  peer->avgms += peer->lookuptimes[0];
3252  cnt++;
3253  }
3254  if (cnt)
3255  peer->avgms /= cnt;
3256  }
3257  }
3258  }
3259  }
3260  }
3261  if (trans->parent) {
3262  /* Unlink from parent if appropriate */
3263  AST_LIST_REMOVE(&trans->parent->trans, trans, parentlist);
3264  if (AST_LIST_EMPTY(&trans->parent->trans)) {
3265  /* Wake up sleeper */
3266  if (trans->parent->pfds[1] > -1) {
3267  if (write(trans->parent->pfds[1], "killa!", 6) < 0) {
3268  ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
3269  }
3270  }
3271  }
3272  }
3273  /* Unlink from all trans */
3274  AST_LIST_REMOVE(&alltrans, trans, all);
3275  destroy_packets(&trans->packets);
3276  destroy_packets(&trans->lasttrans);
3277  AST_SCHED_DEL(sched, trans->autokillid);
3278  if (trans->thread) {
3279  /* If used by a thread, mark as dead and be done */
3280  ast_set_flag(trans, FLAG_DEAD);
3281  } else
3282  ast_free(trans);
3283 }
struct dundi_peer::@443 list
int pfds[2]
Definition: pbx_dundi.c:285
char * lookups[DUNDI_TIMING_HISTORY]
Definition: pbx_dundi.c:327
struct dundi_request * parent
Definition: pbx_dundi.c:268
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
Definition: main/utils.c:2587
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define DUNDI_TIMING_HISTORY
Definition: pbx_dundi.c:164
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define LOG_WARNING
Definition: logger.h:274
Definition: sched.c:76
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
int lookuptimes[DUNDI_TIMING_HISTORY]
Definition: pbx_dundi.c:326
#define NULL
Definition: resample.c:96
struct packetlist lasttrans
Definition: pbx_dundi.c:267
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:274
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Definition: linkedlists.h:855
dundi_eid them_eid
Definition: pbx_dundi.c:251
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
Definition: main/utils.c:2842
int lastms
Definition: pbx_dundi.c:335
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
struct timeval qualtx
Definition: pbx_dundi.c:337
#define AST_SCHED_DEL(sched, id)
Remove a scheduler entry.
Definition: sched.h:46
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
struct dundi_transaction::packetlist packets
char number[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:275
struct dundi_transaction * qualtrans
Definition: pbx_dundi.c:330
int errno
#define LOG_NOTICE
Definition: logger.h:263
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_free(a)
Definition: astmm.h:182
dundi_eid eid
Definition: pbx_dundi.c:304
struct dundi_request::@440 trans
static void destroy_packets(struct packetlist *p)
Definition: pbx_dundi.c:2010
struct dundi_transaction * regtrans
Definition: pbx_dundi.c:329
struct timeval start
Definition: pbx_dundi.c:247

◆ discover_transactions()

static int discover_transactions ( struct dundi_request dr)
static

Definition at line 3525 of file pbx_dundi.c.

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

Referenced by dundi_lookup_internal().

3526 {
3527  struct dundi_transaction *trans;
3528  AST_LIST_LOCK(&peers);
3529  AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) {
3530  dundi_discover(trans);
3531  }
3533  return 0;
3534 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
struct dundi_transaction::@438 parentlist
static int dundi_discover(struct dundi_transaction *trans)
Definition: pbx_dundi.c:3413
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct dundi_request::@440 trans

◆ do_autokill()

static int do_autokill ( const void *  data)
static

Definition at line 3380 of file pbx_dundi.c.

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

3381 {
3382  struct dundi_transaction *trans = (struct dundi_transaction *)data;
3383  char eid_str[20];
3384  ast_log(LOG_NOTICE, "Transaction to '%s' took too long to ACK, destroying\n",
3385  ast_eid_to_str(eid_str, sizeof(eid_str), &trans->them_eid));
3386  trans->autokillid = -1;
3387  destroy_trans(trans, 0); /* We could actually set it to 1 instead of 0, but we won't ;-) */
3388  return 0;
3389 }
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
Definition: main/utils.c:2587
static void destroy_trans(struct dundi_transaction *trans, int fromtimeout)
Definition: pbx_dundi.c:3203
dundi_eid them_eid
Definition: pbx_dundi.c:251
#define ast_log
Definition: astobj2.c:42
#define LOG_NOTICE
Definition: logger.h:263

◆ do_qualify()

static int do_qualify ( const void *  data)
static

Definition at line 4557 of file pbx_dundi.c.

References qualify_peer(), and dundi_peer::qualifyid.

Referenced by qualify_peer().

4558 {
4559  struct dundi_peer *peer = (struct dundi_peer *)data;
4560  peer->qualifyid = -1;
4561  qualify_peer(peer, 0);
4562  return 0;
4563 }
int qualifyid
Definition: pbx_dundi.c:313
static void qualify_peer(struct dundi_peer *peer, int schedonly)
Definition: pbx_dundi.c:4565

◆ do_register()

static int do_register ( const void *  data)
static

Definition at line 4531 of file pbx_dundi.c.

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

Referenced by build_peer().

4532 {
4533  struct dundi_ie_data ied;
4534  struct dundi_peer *peer = (struct dundi_peer *)data;
4535  char eid_str[20];
4536  char eid_str2[20];
4537  ast_debug(1, "Register us as '%s' to '%s'\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->us_eid), ast_eid_to_str(eid_str2, sizeof(eid_str2), &peer->eid));
4539  /* Destroy old transaction if there is one */
4540  if (peer->regtrans)
4541  destroy_trans(peer->regtrans, 0);
4542  peer->regtrans = create_transaction(peer);
4543  if (peer->regtrans) {
4545  memset(&ied, 0, sizeof(ied));
4549  dundi_send(peer->regtrans, DUNDI_COMMAND_REGREQ, 0, 0, &ied);
4550 
4551  } else
4552  ast_log(LOG_NOTICE, "Unable to create new transaction for registering to '%s'!\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
4553 
4554  return 0;
4555 }
#define DUNDI_IE_EXPIRATION
Definition: dundi.h:189
int dundi_ie_append_eid(struct dundi_ie_data *ied, unsigned char ie, dundi_eid *eid)
Definition: dundi-parser.c:610
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
Definition: main/utils.c:2587
#define ast_set_flag(p, flag)
Definition: utils.h:70
Definition: sched.c:76
static int dundi_send(struct dundi_transaction *trans, int cmdresp, int flags, int final, struct dundi_ie_data *ied)
Definition: pbx_dundi.c:3308
dundi_eid us_eid
Definition: pbx_dundi.c:250
#define DUNDI_IE_VERSION
Definition: dundi.h:188
static void destroy_trans(struct dundi_transaction *trans, int fromtimeout)
Definition: pbx_dundi.c:3203
static int do_register(const void *data)
Definition: pbx_dundi.c:4531
int registerid
Definition: pbx_dundi.c:312
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
static struct dundi_transaction * create_transaction(struct dundi_peer *p)
Definition: pbx_dundi.c:3137
#define DUNDI_IE_EID
Definition: dundi.h:182
dundi_eid us_eid
Definition: pbx_dundi.c:308
static int default_expiration
Definition: pbx_dundi.c:199
#define LOG_NOTICE
Definition: logger.h:263
#define DUNDI_DEFAULT_VERSION
Definition: dundi.h:217
int dundi_ie_append_short(struct dundi_ie_data *ied, unsigned char ie, unsigned short value)
Definition: dundi-parser.c:598
dundi_eid eid
Definition: pbx_dundi.c:304
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:565
#define DUNDI_COMMAND_REGREQ
Definition: dundi.h:169
struct dundi_transaction * regtrans
Definition: pbx_dundi.c:329

◆ do_register_expire()

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

Definition at line 1321 of file pbx_dundi.c.

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

1322 {
1323  struct dundi_peer *peer = (struct dundi_peer *)data;
1324  char eid_str[20];
1325 
1326  ast_debug(1, "Register expired for '%s'\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
1327  ast_db_del("dundi/dpeers", dundi_eid_to_str_short(eid_str, sizeof(eid_str), &peer->eid));
1328  peer->registerexpire = -1;
1329  peer->lastms = 0;
1330  ast_sockaddr_setnull(&peer->addr);
1331  return 0;
1332 }
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
Definition: main/utils.c:2587
char * dundi_eid_to_str_short(char *s, int maxlen, dundi_eid *eid)
Definition: dundi-parser.c:54
int registerexpire
Definition: pbx_dundi.c:325
int lastms
Definition: pbx_dundi.c:335
static void ast_sockaddr_setnull(struct ast_sockaddr *addr)
Sets address addr to null.
Definition: netsock2.h:140
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
dundi_eid eid
Definition: pbx_dundi.c:304
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: main/db.c:429
struct ast_sockaddr addr
Definition: pbx_dundi.c:305

◆ drds_destroy()

static void drds_destroy ( struct dundi_result_datastore drds)
static

Definition at line 4199 of file pbx_dundi.c.

References ast_free.

Referenced by drds_destroy_cb(), and dundi_query_read().

4200 {
4201  ast_free(drds);
4202 }
#define ast_free(a)
Definition: astmm.h:182

◆ drds_destroy_cb()

static void drds_destroy_cb ( void *  data)
static

Definition at line 4204 of file pbx_dundi.c.

References drds_destroy().

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

◆ dundi_ack()

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

Definition at line 451 of file pbx_dundi.c.

References DUNDI_COMMAND_ACK, dundi_send(), and NULL.

Referenced by handle_command_response(), and handle_frame().

452 {
453  return dundi_send(trans, DUNDI_COMMAND_ACK, 0, final, NULL);
454 }
static int dundi_send(struct dundi_transaction *trans, int cmdresp, int flags, int final, struct dundi_ie_data *ied)
Definition: pbx_dundi.c:3308
#define NULL
Definition: resample.c:96
#define DUNDI_COMMAND_ACK
Definition: dundi.h:159

◆ dundi_answer_entity()

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

Definition at line 809 of file pbx_dundi.c.

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

810 {
811  struct dundi_query_state *st;
812  int totallen;
813  int x;
814  int skipfirst=0;
815  char eid_str[20];
816  char *s;
817  pthread_t lookupthread;
818 
819  if (ies->eidcount > 1) {
820  /* Since it is a requirement that the first EID is the authenticating host
821  and the last EID is the root, it is permissible that the first and last EID
822  could be the same. In that case, we should go ahead copy only the "root" section
823  since we will not need it for authentication. */
824  if (!ast_eid_cmp(ies->eids[0], ies->eids[ies->eidcount - 1]))
825  skipfirst = 1;
826  }
827  totallen = sizeof(struct dundi_query_state);
828  totallen += (ies->eidcount - skipfirst) * sizeof(dundi_eid);
829  st = ast_calloc(1, totallen);
830  if (st) {
832  memcpy(&st->reqeid, ies->reqeid, sizeof(st->reqeid));
833  st->trans = trans;
834  st->ttl = ies->ttl - 1;
835  if (st->ttl < 0)
836  st->ttl = 0;
837  s = st->fluffy;
838  for (x=skipfirst;ies->eids[x];x++) {
839  st->eids[x-skipfirst] = (dundi_eid *)s;
840  *st->eids[x-skipfirst] = *ies->eids[x];
841  s += sizeof(dundi_eid);
842  }
843  ast_debug(1, "Answering EID query for '%s@%s'!\n", ast_eid_to_str(eid_str, sizeof(eid_str), ies->reqeid), ies->called_context);
844 
845  trans->thread = 1;
846  if (ast_pthread_create_detached(&lookupthread, NULL, dundi_query_thread, st)) {
847  struct dundi_ie_data ied = { 0, };
848  trans->thread = 0;
849  ast_log(LOG_WARNING, "Unable to create thread!\n");
850  ast_free(st);
851  dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of threads");
852  dundi_send(trans, DUNDI_COMMAND_EIDRESPONSE, 0, 1, &ied);
853  return -1;
854  }
855  } else {
856  struct dundi_ie_data ied = { 0, };
858  dundi_send(trans, DUNDI_COMMAND_EIDRESPONSE, 0, 1, &ied);
859  return -1;
860  }
861  return 0;
862 }
dundi_eid * reqeid
Definition: dundi-parser.h:24
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:563
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
Definition: main/utils.c:2587
struct ast_eid dundi_eid
Definition: dundi.h:32
#define LOG_WARNING
Definition: logger.h:274
dundi_eid * eids[DUNDI_MAX_STACK+1]
Definition: pbx_dundi.c:544
struct dundi_transaction * trans
Definition: pbx_dundi.c:552
#define DUNDI_IE_CAUSE
Definition: dundi.h:191
static int dundi_send(struct dundi_transaction *trans, int cmdresp, int flags, int final, struct dundi_ie_data *ied)
Definition: pbx_dundi.c:3308
dundi_eid reqeid
Definition: pbx_dundi.c:546
#define NULL
Definition: resample.c:96
dundi_eid * eids[DUNDI_MAX_STACK+1]
Definition: dundi-parser.h:22
An Entity ID is essentially a MAC address, brief and unique.
Definition: utils.h:786
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
Definition: main/utils.c:2842
int eidcount
Definition: dundi-parser.h:25
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
int dundi_ie_append_cause(struct dundi_ie_data *ied, unsigned char ie, unsigned char cause, char *data)
Definition: dundi-parser.c:499
char * called_context
Definition: dundi-parser.h:26
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
static void * dundi_query_thread(void *data)
Definition: pbx_dundi.c:754
#define DUNDI_COMMAND_EIDRESPONSE
Definition: dundi.h:163
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
char called_context[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:547

◆ dundi_answer_query()

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

Definition at line 1087 of file pbx_dundi.c.

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, permission::list, 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().

1088 {
1089  struct dundi_query_state *st;
1090  int totallen;
1091  int x;
1092  struct dundi_ie_data ied;
1093  char *s;
1094  struct dundi_mapping *cur;
1095  int mapcount = 0;
1096  int skipfirst = 0;
1097 
1098  pthread_t lookupthread;
1099  totallen = sizeof(struct dundi_query_state);
1100  /* Count matching map entries */
1101  AST_LIST_TRAVERSE(&mappings, cur, list) {
1102  if (!strcasecmp(cur->dcontext, ccontext))
1103  mapcount++;
1104  }
1105  /* If no maps, return -1 immediately */
1106  if (!mapcount)
1107  return -1;
1108 
1109  if (ies->eidcount > 1) {
1110  /* Since it is a requirement that the first EID is the authenticating host
1111  and the last EID is the root, it is permissible that the first and last EID
1112  could be the same. In that case, we should go ahead copy only the "root" section
1113  since we will not need it for authentication. */
1114  if (!ast_eid_cmp(ies->eids[0], ies->eids[ies->eidcount - 1]))
1115  skipfirst = 1;
1116  }
1117 
1118  totallen += mapcount * sizeof(struct dundi_mapping);
1119  totallen += (ies->eidcount - skipfirst) * sizeof(dundi_eid);
1120  st = ast_calloc(1, totallen);
1121  if (st) {
1123  ast_copy_string(st->called_number, ies->called_number, sizeof(st->called_number));
1124  st->trans = trans;
1125  st->ttl = ies->ttl - 1;
1126  st->nocache = ies->cbypass;
1127  if (st->ttl < 0)
1128  st->ttl = 0;
1129  s = st->fluffy;
1130  for (x=skipfirst;ies->eids[x];x++) {
1131  st->eids[x-skipfirst] = (dundi_eid *)s;
1132  *st->eids[x-skipfirst] = *ies->eids[x];
1133  st->directs[x-skipfirst] = ies->eid_direct[x];
1134  s += sizeof(dundi_eid);
1135  }
1136  /* Append mappings */
1137  x = 0;
1138  st->maps = (struct dundi_mapping *)s;
1139  AST_LIST_TRAVERSE(&mappings, cur, list) {
1140  if (!strcasecmp(cur->dcontext, ccontext)) {
1141  if (x < mapcount) {
1142  st->maps[x] = *cur;
1143  st->maps[x].list.next = NULL;
1144  x++;
1145  }
1146  }
1147  }
1148  st->nummaps = mapcount;
1149  ast_debug(1, "Answering query for '%s@%s'!\n", ies->called_number, ies->called_context);
1150  trans->thread = 1;
1151  if (ast_pthread_create_detached(&lookupthread, NULL, dundi_lookup_thread, st)) {
1152  trans->thread = 0;
1153  ast_log(LOG_WARNING, "Unable to create thread!\n");
1154  ast_free(st);
1155  memset(&ied, 0, sizeof(ied));
1156  dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of threads");
1157  dundi_send(trans, DUNDI_COMMAND_DPRESPONSE, 0, 1, &ied);
1158  return -1;
1159  }
1160  } else {
1161  ast_log(LOG_WARNING, "Out of memory!\n");
1162  memset(&ied, 0, sizeof(ied));
1163  dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of memory");
1164  dundi_send(trans, DUNDI_COMMAND_DPRESPONSE, 0, 1, &ied);
1165  return -1;
1166  }
1167  return 0;
1168 }
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:292
char called_number[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:548
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:563
struct ast_eid dundi_eid
Definition: dundi.h:32
static void * dundi_lookup_thread(void *data)
Definition: pbx_dundi.c:657
#define LOG_WARNING
Definition: logger.h:274
dundi_eid * eids[DUNDI_MAX_STACK+1]
Definition: pbx_dundi.c:544
struct dundi_mapping * maps
Definition: pbx_dundi.c:549
struct dundi_transaction * trans
Definition: pbx_dundi.c:552
#define DUNDI_IE_CAUSE
Definition: dundi.h:191
static int dundi_send(struct dundi_transaction *trans, int cmdresp, int flags, int final, struct dundi_ie_data *ied)
Definition: pbx_dundi.c:3308
int eid_direct[DUNDI_MAX_STACK+1]
Definition: dundi-parser.h:23
char * called_number
Definition: dundi-parser.h:27
#define NULL
Definition: resample.c:96
struct dundi_mapping::@442 list
dundi_eid * eids[DUNDI_MAX_STACK+1]
Definition: dundi-parser.h:22
An Entity ID is essentially a MAC address, brief and unique.
Definition: utils.h:786
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
Definition: main/utils.c:2842
struct dundi_mapping * next
Definition: pbx_dundi.c:300
int eidcount
Definition: dundi-parser.h:25
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define DUNDI_COMMAND_DPRESPONSE
Definition: dundi.h:161
#define ast_log
Definition: astobj2.c:42
int dundi_ie_append_cause(struct dundi_ie_data *ied, unsigned char ie, unsigned char cause, char *data)
Definition: dundi-parser.c:499
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
char * called_context
Definition: dundi-parser.h:26
#define ast_free(a)
Definition: astmm.h:182
int directs[DUNDI_MAX_STACK+1]
Definition: pbx_dundi.c:545
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
char called_context[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:547

◆ dundi_canmatch()

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

Definition at line 4827 of file pbx_dundi.c.

References DUNDI_FLAG_CANMATCH, and dundi_helper().

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

◆ dundi_debug_output()

static void dundi_debug_output ( const char *  data)
static

Definition at line 356 of file pbx_dundi.c.

References ast_verbose().

Referenced by load_module().

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

◆ dundi_decrypt()

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

Definition at line 1406 of file pbx_dundi.c.

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

Referenced by handle_command_response().

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

◆ dundi_discover()

static int dundi_discover ( struct dundi_transaction trans)
static

Definition at line 3413 of file pbx_dundi.c.

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

Referenced by discover_transactions().

3414 {
3415  struct dundi_ie_data ied;
3416  int x;
3417  if (!trans->parent) {
3418  ast_log(LOG_WARNING, "Tried to discover a transaction with no parent?!?\n");
3419  return -1;
3420  }
3421  memset(&ied, 0, sizeof(ied));
3423  if (!dundi_eid_zero(&trans->us_eid))
3425  for (x=0;x<trans->eidcount;x++)
3426  dundi_ie_append_eid_appropriately(&ied, trans->parent->dcontext, &trans->eids[x], &trans->us_eid);
3429  dundi_ie_append_short(&ied, DUNDI_IE_TTL, trans->ttl);
3430  if (trans->parent->cbypass)
3432  if (trans->autokilltimeout)
3433  trans->autokillid = ast_sched_add(sched, trans->autokilltimeout, do_autokill, trans);
3434  return dundi_send(trans, DUNDI_COMMAND_DPDISCOVER, 0, 0, &ied);
3435 }
#define DUNDI_IE_EID_DIRECT
Definition: dundi.h:185
struct dundi_request * parent
Definition: pbx_dundi.c:268
int dundi_ie_append_eid(struct dundi_ie_data *ied, unsigned char ie, dundi_eid *eid)
Definition: dundi-parser.c:610
#define DUNDI_IE_CACHEBYPASS
Definition: dundi.h:207
dundi_eid eids[DUNDI_MAX_STACK+1]
Definition: pbx_dundi.c:248
#define LOG_WARNING
Definition: logger.h:274
Definition: sched.c:76
static int dundi_send(struct dundi_transaction *trans, int cmdresp, int flags, int final, struct dundi_ie_data *ied)
Definition: pbx_dundi.c:3308
dundi_eid us_eid
Definition: pbx_dundi.c:250
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:274
static void dundi_ie_append_eid_appropriately(struct dundi_ie_data *ied, char *context, dundi_eid *eid, dundi_eid *us)
Definition: pbx_dundi.c:3391
#define DUNDI_IE_VERSION
Definition: dundi.h:188
#define ast_log
Definition: astobj2.c:42
int dundi_ie_append(struct dundi_ie_data *ied, unsigned char ie)
Definition: dundi-parser.c:620
static int do_autokill(const void *data)
Definition: pbx_dundi.c:3380
int dundi_ie_append_str(struct dundi_ie_data *ied, unsigned char ie, char *str)
Definition: dundi-parser.c:605
char number[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:275
#define DUNDI_IE_CALLED_CONTEXT
Definition: dundi.h:183
#define DUNDI_DEFAULT_VERSION
Definition: dundi.h:217
int dundi_ie_append_short(struct dundi_ie_data *ied, unsigned char ie, unsigned short value)
Definition: dundi-parser.c:598
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:565
#define DUNDI_IE_CALLED_NUMBER
Definition: dundi.h:184
int dundi_eid_zero(dundi_eid *eid)
Definition: dundi-parser.c:82
#define DUNDI_COMMAND_DPDISCOVER
Definition: dundi.h:160
#define DUNDI_IE_TTL
Definition: dundi.h:187

◆ dundi_do_lookup()

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

Definition at line 2456 of file pbx_dundi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_copy_string(), ast_tvdiff_ms(), ast_tvnow(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, context, dundi_result::dest, dundi_flags2str(), dundi_lookup(), dundi_result::eid_str, dundi_result::expiration, ast_cli_args::fd, NULL, sort_results(), dundi_result::tech, tmp(), ast_cli_entry::usage, and dundi_result::weight.

2457 {
2458  int res;
2459  char tmp[256];
2460  char fs[80] = "";
2461  char *context;
2462  int x;
2463  int bypass = 0;
2464  struct dundi_result dr[MAX_RESULTS];
2465  struct timeval start;
2466  switch (cmd) {
2467  case CLI_INIT:
2468  e->command = "dundi lookup";
2469  e->usage =
2470  "Usage: dundi lookup <number>[@context] [bypass]\n"
2471  " Lookup the given number within the given DUNDi context\n"
2472  "(or e164 if none is specified). Bypasses cache if 'bypass'\n"
2473  "keyword is specified.\n";
2474  return NULL;
2475  case CLI_GENERATE:
2476  return NULL;
2477  }
2478 
2479  if ((a->argc < 3) || (a->argc > 4)) {
2480  return CLI_SHOWUSAGE;
2481  }
2482  if (a->argc > 3) {
2483  if (!strcasecmp(a->argv[3], "bypass")) {
2484  bypass=1;
2485  } else {
2486  return CLI_SHOWUSAGE;
2487  }
2488  }
2489  ast_copy_string(tmp, a->argv[2], sizeof(tmp));
2490  context = strchr(tmp, '@');
2491  if (context) {
2492  *context = '\0';
2493  context++;
2494  }
2495  start = ast_tvnow();
2496  res = dundi_lookup(dr, MAX_RESULTS, NULL, context, tmp, bypass);
2497 
2498  if (res < 0)
2499  ast_cli(a->fd, "DUNDi lookup returned error.\n");
2500  else if (!res)
2501  ast_cli(a->fd, "DUNDi lookup returned no results.\n");
2502  else
2503  sort_results(dr, res);
2504  for (x=0;x<res;x++) {
2505  ast_cli(a->fd, "%3d. %5d %s/%s (%s)\n", x + 1, dr[x].weight, dr[x].tech, dr[x].dest, dundi_flags2str(fs, sizeof(fs), dr[x].flags));
2506  ast_cli(a->fd, " from %s, expires in %d s\n", dr[x].eid_str, dr[x].expiration);
2507  }
2508  ast_cli(a->fd, "DUNDi lookup completed in %" PRIi64 " ms\n", ast_tvdiff_ms(ast_tvnow(), start));
2509  return CLI_SUCCESS;
2510 }
static float dr[4]
Definition: tdd.c:58
int dundi_lookup(struct dundi_result *result, int maxret, struct ast_channel *chan, const char *dcontext, const char *number, int cbypass)
Lookup the given number in the given dundi context. Lookup number in a given dundi context (if unspec...
Definition: pbx_dundi.c:3926
static void sort_results(struct dundi_result *results, int count)
Definition: pbx_dundi.c:2451
const int argc
Definition: cli.h:160
static int tmp()
Definition: bt_open.c:389
#define MAX_RESULTS
Definition: pbx_dundi.c:153
Definition: cli.h:152
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
const int fd
Definition: cli.h:159
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
char * dundi_flags2str(char *buf, int bufsiz, int flags)
Definition: dundi-parser.c:246

◆ dundi_do_precache()

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

Definition at line 2512 of file pbx_dundi.c.

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

2513 {
2514  int res;
2515  char tmp[256];
2516  char *context;
2517  struct timeval start;
2518  switch (cmd) {
2519  case CLI_INIT:
2520  e->command = "dundi precache";
2521  e->usage =
2522  "Usage: dundi precache <number>[@context]\n"
2523  " Lookup the given number within the given DUNDi context\n"
2524  "(or e164 if none is specified) and precaches the results to any\n"
2525  "upstream DUNDi push servers.\n";
2526  return NULL;
2527  case CLI_GENERATE:
2528  return NULL;
2529  }
2530  if ((a->argc < 3) || (a->argc > 3)) {
2531  return CLI_SHOWUSAGE;
2532  }
2533  ast_copy_string(tmp, a->argv[2], sizeof(tmp));
2534  context = strchr(tmp, '@');
2535  if (context) {
2536  *context = '\0';
2537  context++;
2538  }
2539  start = ast_tvnow();
2540  res = dundi_precache(context, tmp);
2541 
2542  if (res < 0)
2543  ast_cli(a->fd, "DUNDi precache returned error.\n");
2544  else if (!res)
2545  ast_cli(a->fd, "DUNDi precache returned no error.\n");
2546  ast_cli(a->fd, "DUNDi lookup completed in %" PRIi64 " ms\n", ast_tvdiff_ms(ast_tvnow(), start));
2547  return CLI_SUCCESS;
2548 }
const int argc
Definition: cli.h:160
static int tmp()
Definition: bt_open.c:389
Definition: cli.h:152
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
const int fd
Definition: cli.h:159
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
int dundi_precache(const char *context, const char *number)
Pre-cache to push upstream peers.
Definition: pbx_dundi.c:4068
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ dundi_do_query()

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

Definition at line 2550 of file pbx_dundi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_copy_string(), ast_str_to_eid(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, context, dundi_entity_info::country, dundi_query_eid(), dundi_entity_info::email, ast_cli_args::fd, 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.

2551 {
2552  int res;
2553  char tmp[256];
2554  char *context;
2555  dundi_eid eid;
2556  struct dundi_entity_info dei;
2557  switch (cmd) {
2558  case CLI_INIT:
2559  e->command = "dundi query";
2560  e->usage =
2561  "Usage: dundi query <entity>[@context]\n"
2562  " Attempts to retrieve contact information for a specific\n"
2563  "DUNDi entity identifier (EID) within a given DUNDi context (or\n"
2564  "e164 if none is specified).\n";
2565  return NULL;
2566  case CLI_GENERATE:
2567  return NULL;
2568  }
2569  if ((a->argc < 3) || (a->argc > 3)) {
2570  return CLI_SHOWUSAGE;
2571  }
2572  if (ast_str_to_eid(&eid, a->argv[2])) {
2573  ast_cli(a->fd, "'%s' is not a valid EID!\n", a->argv[2]);
2574  return CLI_SHOWUSAGE;
2575  }
2576  ast_copy_string(tmp, a->argv[2], sizeof(tmp));
2577  context = strchr(tmp, '@');
2578  if (context) {
2579  *context = '\0';
2580  context++;
2581  }
2582  res = dundi_query_eid(&dei, context, eid);
2583  if (res < 0)
2584  ast_cli(a->fd, "DUNDi Query EID returned error.\n");
2585  else if (!res)
2586  ast_cli(a->fd, "DUNDi Query EID returned no results.\n");
2587  else {
2588  ast_cli(a->fd, "DUNDi Query EID succeeded:\n");
2589  ast_cli(a->fd, "Department: %s\n", dei.orgunit);
2590  ast_cli(a->fd, "Organization: %s\n", dei.org);
2591  ast_cli(a->fd, "City/Locality: %s\n", dei.locality);
2592  ast_cli(a->fd, "State/Province: %s\n", dei.stateprov);
2593  ast_cli(a->fd, "Country: %s\n", dei.country);
2594  ast_cli(a->fd, "E-mail: %s\n", dei.email);
2595  ast_cli(a->fd, "Phone: %s\n", dei.phone);
2596  ast_cli(a->fd, "IP Address: %s\n", dei.ipaddr);
2597  }
2598  return CLI_SUCCESS;
2599 }
int dundi_query_eid(struct dundi_entity_info *dei, const char *dcontext, dundi_eid eid)
Retrieve information on a specific EID.
Definition: pbx_dundi.c:4121
const int argc
Definition: cli.h:160
static int tmp()
Definition: bt_open.c:389
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
An Entity ID is essentially a MAC address, brief and unique.
Definition: utils.h:786
const int fd
Definition: cli.h:159
int ast_str_to_eid(struct ast_eid *eid, const char *s)
Convert a string into an EID.
Definition: main/utils.c:2825
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ dundi_encrypt()

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

Definition at line 1428 of file pbx_dundi.c.

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

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

◆ dundi_error_output()

static void dundi_error_output ( const char *  data)
static

Definition at line 362 of file pbx_dundi.c.

References ast_log, and LOG_WARNING.

Referenced by load_module().

363 {
364  ast_log(LOG_WARNING, "%s", data);
365 }
#define LOG_WARNING
Definition: logger.h:274
#define ast_log
Definition: astobj2.c:42

◆ dundi_exec()

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

Definition at line 4832 of file pbx_dundi.c.

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

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

◆ dundi_exists()

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

Definition at line 4822 of file pbx_dundi.c.

References DUNDI_FLAG_EXISTS, and dundi_helper().

4823 {
4824  return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_EXISTS);
4825 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
static int priority
static int dundi_helper(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *data, int flag)
Definition: pbx_dundi.c:4783
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ dundi_flush()

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

Definition at line 2357 of file pbx_dundi.c.

References ast_cli_args::argc, ast_cli_args::argv, 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, ast_cli_args::fd, permission::list, dundi_peer::lookups, dundi_peer::lookuptimes, NULL, and ast_cli_entry::usage.

2358 {
2359  int stats = 0;
2360  switch (cmd) {
2361  case CLI_INIT:
2362  e->command = "dundi flush [stats]";
2363  e->usage =
2364  "Usage: dundi flush [stats]\n"
2365  " Flushes DUNDi answer cache, used primarily for debug. If\n"
2366  "'stats' is present, clears timer statistics instead of normal\n"
2367  "operation.\n";
2368  return NULL;
2369  case CLI_GENERATE:
2370  return NULL;
2371  }
2372  if ((a->argc < 2) || (a->argc > 3)) {
2373  return CLI_SHOWUSAGE;
2374  }
2375  if (a->argc > 2) {
2376  if (!strcasecmp(a->argv[2], "stats")) {
2377  stats = 1;
2378  } else {
2379  return CLI_SHOWUSAGE;
2380  }
2381  }
2382  if (stats) {
2383  /* Flush statistics */
2384  struct dundi_peer *p;
2385  int x;
2386  AST_LIST_LOCK(&peers);
2387  AST_LIST_TRAVERSE(&peers, p, list) {
2388  for (x = 0;x < DUNDI_TIMING_HISTORY; x++) {
2389  ast_free(p->lookups[x]);
2390  p->lookups[x] = NULL;
2391  p->lookuptimes[x] = 0;
2392  }
2393  p->avgms = 0;
2394  }
2396  } else {
2397  ast_db_deltree("dundi/cache", NULL);
2398  ast_cli(a->fd, "DUNDi Cache Flushed\n");
2399  }
2400  return CLI_SUCCESS;
2401 }
struct dundi_peer::@443 list
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
char * lookups[DUNDI_TIMING_HISTORY]
Definition: pbx_dundi.c:327
#define DUNDI_TIMING_HISTORY
Definition: pbx_dundi.c:164
const int argc
Definition: cli.h:160
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
Definition: cli.h:152
int lookuptimes[DUNDI_TIMING_HISTORY]
Definition: pbx_dundi.c:326
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
const int fd
Definition: cli.h:159
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_free(a)
Definition: astmm.h:182
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
int ast_db_deltree(const char *family, const char *keytree)
Delete one or more entries in astdb.
Definition: main/db.c:457

◆ dundi_helper()

static int dundi_helper ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority,
const char *  data,
int  flag 
)
static

Definition at line 4783 of file pbx_dundi.c.

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

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

4784 {
4785  struct dundi_result results[MAX_RESULTS];
4786  int res;
4787  int x;
4788  int found = 0;
4789  if (!strncasecmp(context, "macro-", 6)) {
4790  if (!chan) {
4791  ast_log(LOG_NOTICE, "Can't use macro mode without a channel!\n");
4792  return -1;
4793  }
4794  /* If done as a macro, use macro extension */
4795  if (!strcasecmp(exten, "s")) {
4796  exten = pbx_builtin_getvar_helper(chan, "ARG1");
4797  if (ast_strlen_zero(exten))
4798  exten = ast_channel_macroexten(chan);
4799  if (ast_strlen_zero(exten))
4800  exten = ast_channel_exten(chan);
4801  if (ast_strlen_zero(exten)) {
4802  ast_log(LOG_WARNING, "Called in Macro mode with no ARG1 or MACRO_EXTEN?\n");
4803  return -1;
4804  }
4805  }
4806  if (ast_strlen_zero(data))
4807  data = "e164";
4808  } else {
4809  if (ast_strlen_zero(data))
4810  data = context;
4811  }
4812  res = dundi_lookup(results, MAX_RESULTS, chan, data, exten, 0);
4813  for (x=0;x<res;x++) {
4814  if (ast_test_flag(results + x, flag))
4815  found++;
4816  }
4817  if (found >= priority)
4818  return 1;
4819  return 0;
4820 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
int dundi_lookup(struct dundi_result *result, int maxret, struct ast_channel *chan, const char *dcontext, const char *number, int cbypass)
Lookup the given number in the given dundi context. Lookup number in a given dundi context (if unspec...
Definition: pbx_dundi.c:3926
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define LOG_WARNING
Definition: logger.h:274
#define MAX_RESULTS
Definition: pbx_dundi.c:153
static int priority
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
const char * ast_channel_exten(const struct ast_channel *chan)
#define LOG_NOTICE
Definition: logger.h:263
long int flag
Definition: f2c.h:83
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
const char * ast_channel_macroexten(const struct ast_channel *chan)

◆ dundi_ie_append_eid_appropriately()

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

Definition at line 3391 of file pbx_dundi.c.

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

Referenced by dundi_discover().

3392 {
3393  struct dundi_peer *p;
3394  if (!ast_eid_cmp(eid, us)) {
3396  return;
3397  }
3398  AST_LIST_LOCK(&peers);
3399  AST_LIST_TRAVERSE(&peers, p, list) {
3400  if (!ast_eid_cmp(&p->eid, eid)) {
3401  if (has_permission(&p->include, context))
3403  else
3404  dundi_ie_append_eid(ied, DUNDI_IE_EID, eid);
3405  break;
3406  }
3407  }
3408  if (!p)
3409  dundi_ie_append_eid(ied, DUNDI_IE_EID, eid);
3411 }
struct dundi_peer::@443 list
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define DUNDI_IE_EID_DIRECT
Definition: dundi.h:185
int dundi_ie_append_eid(struct dundi_ie_data *ied, unsigned char ie, dundi_eid *eid)
Definition: dundi-parser.c:610
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
Definition: main/utils.c:2842
static int has_permission(struct permissionlist *permlist, char *cont)
Definition: pbx_dundi.c:367
#define DUNDI_IE_EID
Definition: dundi.h:182
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
dundi_eid eid
Definition: pbx_dundi.c:304
struct permissionlist include
Definition: pbx_dundi.c:307
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ dundi_lookup()

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

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

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

Definition at line 3926 of file pbx_dundi.c.

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

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

3927 {
3928  struct dundi_hint_metadata hmd;
3929  dundi_eid *avoid[1] = { NULL, };
3930  int direct[1] = { 0, };
3931  int expiration = dundi_cache_time;
3932  memset(&hmd, 0, sizeof(hmd));
3934  return dundi_lookup_internal(result, maxret, chan, dcontext, number, dundi_ttl, 0, &hmd, &expiration, cbypass, 0, NULL, avoid, direct);
3935 }
static int dundi_cache_time
Definition: pbx_dundi.c:196
static int dundi_lookup_internal(struct dundi_result *result, int maxret, struct ast_channel *chan, const char *dcontext, const char *number, int ttl, int blockempty, struct dundi_hint_metadata *md, int *expiration, int cybpass, int modeselect, dundi_eid *skip, dundi_eid *avoid[], int direct[])
Definition: pbx_dundi.c:3824
#define NULL
Definition: resample.c:96
An Entity ID is essentially a MAC address, brief and unique.
Definition: utils.h:786
Number structure.
Definition: app_followme.c:154
static int dundi_ttl
Definition: pbx_dundi.c:194

◆ dundi_lookup_internal()

static int dundi_lookup_internal ( struct dundi_result result,
int  maxret,
struct ast_channel chan,
const char *  dcontext,
const char *  number,
int  ttl,
int  blockempty,
struct dundi_hint_metadata md,
int *  expiration,
int  cybpass,
int  modeselect,
dundi_eid skip,
dundi_eid avoid[],
int  direct[] 
)
static

Definition at line 3824 of file pbx_dundi.c.

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(), dundi_request::cbypass, check_request(), dundi_request::crc32, dundi_request::dcontext, discover_transactions(), dundi_request::dr, DUNDI_FLUFF_TIME, DUNDI_HINT_TTL_EXPIRED, DUNDI_TTL_TIME, errno, dundi_request::expiration, dundi_request::hmd, LOG_WARNING, dundi_request::maxcount, NULL, dundi_request::number, optimize_transactions(), order, dundi_request::pfds, register_request(), dundi_request::respcount, result, dundi_request::root_eid, dundi_request::trans, and unregister_request().

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

3825 {
3826  int res;
3827  struct dundi_request dr, *pending;
3828  dundi_eid *rooteid=NULL;
3829  int x;
3830  int ttlms;
3831  int ms;
3832  int foundcache;
3833  int skipped=0;
3834  int order=0;
3835  char eid_str[20];
3836  struct timeval start;
3837 
3838  /* Don't do anthing for a hungup channel */
3839  if (chan && ast_check_hangup(chan))
3840  return 0;
3841 
3842  ttlms = DUNDI_FLUFF_TIME + ttl * DUNDI_TTL_TIME;
3843 
3844  for (x=0;avoid[x];x++)
3845  rooteid = avoid[x];
3846  /* Now perform real check */
3847  memset(&dr, 0, sizeof(dr));
3848  if (pipe(dr.pfds)) {
3849  ast_log(LOG_WARNING, "pipe failed: %s\n" , strerror(errno));
3850  return -1;
3851  }
3852  dr.dr = result;
3853  dr.hmd = hmd;
3854  dr.maxcount = maxret;
3855  dr.expiration = *expiration;
3856  dr.cbypass = cbypass;
3857  dr.crc32 = avoid_crc32(avoid);
3858  ast_copy_string(dr.dcontext, dcontext ? dcontext : "e164", sizeof(dr.dcontext));
3859  ast_copy_string(dr.number, number, sizeof(dr.number));
3860  if (rooteid)
3861  dr.root_eid = *rooteid;
3862  res = register_request(&dr, &pending);
3863  if (res) {
3864  /* Already a request */
3865  if (rooteid && !ast_eid_cmp(&dr.root_eid, &pending->root_eid)) {
3866  /* This is on behalf of someone else. Go ahead and close this out since
3867  they'll get their answer anyway. */
3868  ast_debug(1, "Oooh, duplicate request for '%s@%s' for '%s'\n",
3869  dr.number,dr.dcontext,ast_eid_to_str(eid_str, sizeof(eid_str), &dr.root_eid));
3870  close(dr.pfds[0]);
3871  close(dr.pfds[1]);
3872  return -2;
3873  } else {
3874  /* Wait for the cache to populate */
3875  ast_debug(1, "Waiting for similar request for '%s@%s' for '%s'\n",
3876  dr.number,dr.dcontext,ast_eid_to_str(eid_str, sizeof(eid_str), &pending->root_eid));
3877  start = ast_tvnow();
3878  while(check_request(pending) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms) && (!chan || !ast_check_hangup(chan))) {
3879  /* XXX Would be nice to have a way to poll/select here XXX */
3880  /* XXX this is a busy wait loop!!! */
3881  usleep(1);
3882  }
3883  /* Continue on as normal, our cache should kick in */
3884  }
3885  }
3886  /* Create transactions */
3887  do {
3888  order = skipped;
3889  skipped = 0;
3890  foundcache = 0;
3891  build_transactions(&dr, ttl, order, &foundcache, &skipped, blockempty, cbypass, modeselect, skip, avoid, direct);
3892  } while (skipped && !foundcache && AST_LIST_EMPTY(&dr.trans));
3893  /* If no TTL, abort and return 0 now after setting TTL expired hint. Couldn't
3894  do this earlier because we didn't know if we were going to have transactions
3895  or not. */
3896  if (!ttl) {
3898  abort_request(&dr);
3900  close(dr.pfds[0]);
3901  close(dr.pfds[1]);
3902  return 0;
3903  }
3904 
3905  /* Optimize transactions */
3906  optimize_transactions(&dr, order);
3907  /* Actually perform transactions */
3909  /* Wait for transaction to come back */
3910  start = ast_tvnow();
3911  while (!AST_LIST_EMPTY(&dr.trans) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms) && (!chan || !ast_check_hangup(chan))) {
3912  ms = 100;
3913  ast_waitfor_n_fd(dr.pfds, 1, &ms, NULL);
3914  }
3915  if (chan && ast_check_hangup(chan))
3916  ast_debug(1, "Hrm, '%s' hungup before their query for %s@%s finished\n", ast_channel_name(chan), dr.number, dr.dcontext);
3917  cancel_request(&dr);
3919  res = dr.respcount;
3920  *expiration = dr.expiration;
3921  close(dr.pfds[0]);
3922  close(dr.pfds[1]);
3923  return res;
3924 }
static float dr[4]
Definition: tdd.c:58
static int discover_transactions(struct dundi_request *dr)
Definition: pbx_dundi.c:3525
#define DUNDI_FLUFF_TIME
Definition: dundi.h:211
static int register_request(struct dundi_request *dr, struct dundi_request **pending)
Definition: pbx_dundi.c:3758
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
Definition: main/utils.c:2587
#define LOG_WARNING
Definition: logger.h:274
static void cancel_request(struct dundi_request *dr)
Definition: pbx_dundi.c:3674
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
#define NULL
Definition: resample.c:96
An Entity ID is essentially a MAC address, brief and unique.
Definition: utils.h:786
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
Definition: main/utils.c:2842
Number structure.
Definition: app_followme.c:154
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception)
Waits for input on an fd.
Definition: channel.c:2989
integer order
Definition: analys.c:66
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
#define DUNDI_TTL_TIME
Definition: dundi.h:212
static unsigned long avoid_crc32(dundi_eid *avoid[])
Definition: pbx_dundi.c:3809
static void unregister_request(struct dundi_request *dr)
Definition: pbx_dundi.c:3788
int errno
static void abort_request(struct dundi_request *dr)
Definition: pbx_dundi.c:3688
dundi_eid root_eid
Definition: pbx_dundi.c:277
static int check_request(struct dundi_request *dr)
Definition: pbx_dundi.c:3795
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
const char * ast_channel_name(const struct ast_channel *chan)
static PGresult * result
Definition: cel_pgsql.c:88
#define ast_set_flag_nonstd(p, flag)
Definition: utils.h:176
static int optimize_transactions(struct dundi_request *dr, int order)
Definition: pbx_dundi.c:3584
static void build_transactions(struct dundi_request *dr, int ttl, int order, int *foundcache, int *skipped, int blockempty, int nocache, int modeselect, dundi_eid *skip, dundi_eid *avoid[], int directs[])
Definition: pbx_dundi.c:3700

◆ dundi_lookup_local()

static int dundi_lookup_local ( struct dundi_result dr,
struct dundi_mapping map,
char *  called_number,
dundi_eid us_eid,
int  anscnt,
struct dundi_hint_metadata hmd 
)
static

Definition at line 578 of file pbx_dundi.c.

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(), dundi_result::dest, dundi_mapping::dest, destroy_trans(), dundi_cache_time, DUNDI_FLAG_CANMATCH, DUNDI_FLAG_EXISTS, DUNDI_FLAG_IGNOREPAT, DUNDI_FLAG_INTERNAL_NOPARTIAL, DUNDI_FLAG_MATCHMORE, DUNDI_HINT_DONT_ASK, dundi_result::eid, ast_var_t::entries, dundi_result::expiration, dundi_hint_metadata::exten, get_mapping_weight(), dundi_mapping::lcontext, NULL, dundi_mapping::options, pbx_substitute_variables_varshead(), dundi_result::tech, dundi_mapping::tech, tech2str(), dundi_result::techint, tmp(), and dundi_result::weight.

Referenced by dundi_lookup_thread(), and precache_trans().

579 {
580  struct ast_flags flags = {0};
581  int x;
582  if (!ast_strlen_zero(map->lcontext)) {
583  if (ast_exists_extension(NULL, map->lcontext, called_number, 1, NULL))
585  if (ast_canmatch_extension(NULL, map->lcontext, called_number, 1, NULL))
587  if (ast_matchmore_extension(NULL, map->lcontext, called_number, 1, NULL))
589  if (ast_ignore_pattern(map->lcontext, called_number))
591 
592  /* Clearly we can't say 'don't ask' anymore if we found anything... */
593  if (ast_test_flag(&flags, AST_FLAGS_ALL))
595 
597  /* Skip partial answers */
599  }
600  if (ast_test_flag(&flags, AST_FLAGS_ALL)) {
601  struct varshead headp;
602  struct ast_var_t *newvariable;
603  ast_set_flag(&flags, map->options & 0xffff);
604  ast_copy_flags(dr + anscnt, &flags, AST_FLAGS_ALL);
605  dr[anscnt].techint = map->tech;
606  dr[anscnt].expiration = dundi_cache_time;
607  ast_copy_string(dr[anscnt].tech, tech2str(map->tech), sizeof(dr[anscnt].tech));
608  dr[anscnt].eid = *us_eid;
609  ast_eid_to_str(dr[anscnt].eid_str, sizeof(dr[anscnt].eid_str), &dr[anscnt].eid);
610  if (ast_test_flag(&flags, DUNDI_FLAG_EXISTS)) {
612  if ((newvariable = ast_var_assign("NUMBER", called_number))) {
613  AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
614  }
615  if ((newvariable = ast_var_assign("EID", dr[anscnt].eid_str))) {
616  AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
617  }
618  if ((newvariable = ast_var_assign("SECRET", cursecret))) {
619  AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
620  }
621  if ((newvariable = ast_var_assign("IPADDR", ipaddr))) {
622  AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
623  }
624  pbx_substitute_variables_varshead(&headp, map->dest, dr[anscnt].dest, sizeof(dr[anscnt].dest));
625  dr[anscnt].weight = get_mapping_weight(map, &headp);
626  while ((newvariable = AST_LIST_REMOVE_HEAD(&headp, entries)))
627  ast_var_delete(newvariable);
628  } else {
629  dr[anscnt].dest[0] = '\0';
630  dr[anscnt].weight = get_mapping_weight(map, NULL);
631  }
632  anscnt++;
633  } else {
634  /* No answers... Find the fewest number of digits from the
635  number for which we have no answer. */
636  char tmp[AST_MAX_EXTENSION + 1] = "";
637  for (x = 0; x < (sizeof(tmp) - 1); x++) {
638  tmp[x] = called_number[x];
639  if (!tmp[x])
640  break;
641  if (!ast_canmatch_extension(NULL, map->lcontext, tmp, 1, NULL)) {
642  /* Oops found something we can't match. If this is longer
643  than the running hint, we have to consider it */
644  if (strlen(tmp) > strlen(hmd->exten)) {
645  ast_copy_string(hmd->exten, tmp, sizeof(hmd->exten));
646  }
647  break;
648  }
649  }
650  }
651  }
652  return anscnt;
653 }
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:4199
char dest[512]
Definition: pbx_dundi.c:299
int weight
Definition: dundi.h:227
char lcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:293
static int dundi_cache_time
Definition: pbx_dundi.c:196
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
Definition: main/utils.c:2587
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ast_clear_flag_nonstd(p, flag)
Definition: utils.h:180
#define ast_set_flag(p, flag)
Definition: utils.h:70
static char * tech2str(int tech)
Definition: pbx_dundi.c:380
static int tmp()
Definition: bt_open.c:389
unsigned int flags
Definition: utils.h:200
int ast_ignore_pattern(const char *context, const char *pattern)
Checks to see if a number should be ignored.
Definition: pbx.c:6921
char dest[256]
Definition: dundi.h:233
#define ast_copy_flags(dest, src, flagz)
Definition: utils.h:84
#define NULL
Definition: resample.c:96
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:4194
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define DUNDI_FLAG_INTERNAL_NOPARTIAL
Definition: pbx_dundi.c:176
#define AST_MAX_EXTENSION
Definition: channel.h:135
char tech[10]
Definition: dundi.h:232
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
int expiration
Definition: dundi.h:228
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:4179
static char ipaddr[80]
Definition: pbx_dundi.c:210
void ast_var_delete(struct ast_var_t *var)
Definition: extconf.c:2473
int techint
Definition: dundi.h:229
dundi_eid eid
Definition: dundi.h:230
static int get_mapping_weight(struct dundi_mapping *map, struct varshead *headp)
Definition: pbx_dundi.c:559
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
struct ast_var_t::@249 entries
#define AST_FLAGS_ALL
Definition: utils.h:196
#define ast_var_assign(name, value)
Definition: chanvars.h:40
char exten[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:233
Structure used to handle boolean flags.
Definition: utils.h:199
#define ast_clear_flag(p, flag)
Definition: utils.h:77
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:680
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static char cursecret[80]
Definition: pbx_dundi.c:209
void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count)

◆ dundi_lookup_thread()

static void* dundi_lookup_thread ( void *  data)
static