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

Definition at line 657 of file pbx_dundi.c.

References ast_debug, ast_eid_to_str(), ast_free, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_test_flag, ast_test_flag_nonstd, dundi_query_state::called_context, dundi_query_state::called_number, destroy_trans(), dundi_query_state::directs, dundi_cache_time, DUNDI_CAUSE_DUPLICATE, DUNDI_COMMAND_DPRESPONSE, DUNDI_HINT_DONT_ASK, DUNDI_HINT_UNAFFECTED, DUNDI_IE_ANSWER, dundi_ie_append_answer(), dundi_ie_append_cause(), dundi_ie_append_hint(), dundi_ie_append_short(), DUNDI_IE_CAUSE, DUNDI_IE_EXPIRATION, DUNDI_IE_HINT, dundi_lookup_internal(), dundi_lookup_local(), dundi_send(), dundi_query_state::eids, dundi_result::expiration, dundi_hint_metadata::exten, FLAG_DEAD, dundi_hint_metadata::flags, dundi_query_state::maps, max, dundi_query_state::nocache, NULL, dundi_query_state::nummaps, dundi_transaction::thread, dundi_query_state::trans, dundi_query_state::ttl, dundi_transaction::us_eid, weight, and dundi_result::weight.

Referenced by dundi_answer_query().

658 {
659  struct dundi_query_state *st = data;
660  struct dundi_result dr[MAX_RESULTS];
661  struct dundi_ie_data ied;
662  struct dundi_hint_metadata hmd;
663  char eid_str[20];
664  int res, x;
665  int ouranswers=0;
666  int max = 999999;
667  int expiration = dundi_cache_time;
668 
669  ast_debug(1, "Whee, looking up '%s@%s' for '%s'\n", st->called_number, st->called_context,
670  st->eids[0] ? ast_eid_to_str(eid_str, sizeof(eid_str), st->eids[0]) : "ourselves");
671  memset(&ied, 0, sizeof(ied));
672  memset(&dr, 0, sizeof(dr));
673  memset(&hmd, 0, sizeof(hmd));
674  /* Assume 'don't ask for anything' and 'unaffected', no TTL expired */
676  for (x=0;x<st->nummaps;x++)
677  ouranswers = dundi_lookup_local(dr, st->maps + x, st->called_number, &st->trans->us_eid, ouranswers, &hmd);
678  if (ouranswers < 0)
679  ouranswers = 0;
680  for (x=0;x<ouranswers;x++) {
681  if (dr[x].weight < max)
682  max = dr[x].weight;
683  }
684 
685  if (max) {
686  /* If we do not have a canonical result, keep looking */
687  res = dundi_lookup_internal(dr + ouranswers, MAX_RESULTS - ouranswers, NULL, st->called_context, st->called_number, st->ttl, 1, &hmd, &expiration, st->nocache, 0, NULL, st->eids, st->directs);
688  if (res > 0) {
689  /* Append answer in result */
690  ouranswers += res;
691  } else {
692  if ((res < -1) && (!ouranswers))
693  dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_DUPLICATE, "Duplicate Request Pending");
694  }
695  }
697  /* Truncate if "don't ask" isn't present */
699  hmd.exten[0] = '\0';
700  if (ast_test_flag(st->trans, FLAG_DEAD)) {
701  ast_debug(1, "Our transaction went away!\n");
702  st->trans->thread = 0;
703  destroy_trans(st->trans, 0);
704  } else {
705  for (x=0;x<ouranswers;x++) {
706  /* Add answers */
707  if (dr[x].expiration && (expiration > dr[x].expiration))
708  expiration = dr[x].expiration;
709  dundi_ie_append_answer(&ied, DUNDI_IE_ANSWER, &dr[x].eid, dr[x].techint, dr[x].flags, dr[x].weight, dr[x].dest);
710  }
711  dundi_ie_append_hint(&ied, DUNDI_IE_HINT, hmd.flags, hmd.exten);
712  dundi_ie_append_short(&ied, DUNDI_IE_EXPIRATION, expiration);
713  dundi_send(st->trans, DUNDI_COMMAND_DPRESPONSE, 0, 1, &ied);
714  st->trans->thread = 0;
715  }
717  ast_free(st);
718  return NULL;
719 }
static float dr[4]
Definition: tdd.c:58
#define DUNDI_IE_EXPIRATION
Definition: dundi.h:189
static int dundi_lookup_local(struct dundi_result *dr, struct dundi_mapping *map, char *called_number, dundi_eid *us_eid, int anscnt, struct dundi_hint_metadata *hmd)
Definition: pbx_dundi.c:578
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
char called_number[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:548
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_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
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
#define MAX_RESULTS
Definition: pbx_dundi.c:153
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 dundi_ie_append_hint(struct dundi_ie_data *ied, unsigned char ie, unsigned short flags, char *data)
Definition: dundi-parser.c:518
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
dundi_eid us_eid
Definition: pbx_dundi.c:250
static void destroy_trans(struct dundi_transaction *trans, int fromtimeout)
Definition: pbx_dundi.c:3203
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define DUNDI_COMMAND_DPRESPONSE
Definition: dundi.h:161
int dundi_ie_append_cause(struct dundi_ie_data *ied, unsigned char ie, unsigned char cause, char *data)
Definition: dundi-parser.c:499
char weight
#define DUNDI_IE_HINT
Definition: dundi.h:197
int dundi_ie_append_short(struct dundi_ie_data *ied, unsigned char ie, unsigned short value)
Definition: dundi-parser.c:598
unsigned short flags
Definition: pbx_dundi.c:232
#define ast_free(a)
Definition: astmm.h:182
int directs[DUNDI_MAX_STACK+1]
Definition: pbx_dundi.c:545
#define ast_test_flag_nonstd(p, flag)
Definition: utils.h:173
#define DUNDI_IE_ANSWER
Definition: dundi.h:186
int dundi_ie_append_answer(struct dundi_ie_data *ied, unsigned char ie, dundi_eid *eid, unsigned char protocol, unsigned short flags, unsigned short weight, char *data)
Definition: dundi-parser.c:559
char called_context[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:547
#define max(a, b)
Definition: f2c.h:198

◆ dundi_matchmore()

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

Definition at line 4887 of file pbx_dundi.c.

References DUNDI_FLAG_MATCHMORE, and dundi_helper().

4888 {
4889  return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_MATCHMORE);
4890 }
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_precache()

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

Pre-cache to push upstream peers.

Definition at line 4068 of file pbx_dundi.c.

References dundi_precache_internal(), and NULL.

Referenced by dundi_do_precache(), and process_precache().

4069 {
4070  dundi_eid *avoid[1] = { NULL, };
4072 }
#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
static int dundi_precache_internal(const char *context, const char *number, int ttl, dundi_eid *avoids[])
Definition: pbx_dundi.c:3996
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ dundi_precache_full()

static void dundi_precache_full ( void  )
static

Definition at line 3972 of file pbx_dundi.c.

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

Referenced by set_config().

3973 {
3974  struct dundi_mapping *cur;
3975  struct ast_context *con;
3976  struct ast_exten *e;
3977 
3978  AST_LIST_TRAVERSE(&mappings, cur, list) {
3979  ast_log(LOG_NOTICE, "Should precache context '%s'\n", cur->dcontext);
3981  con = NULL;
3982  while ((con = ast_walk_contexts(con))) {
3983  if (strcasecmp(cur->lcontext, ast_get_context_name(con)))
3984  continue;
3985  /* Found the match, now queue them all up */
3986  ast_rdlock_context(con);
3987  e = NULL;
3988  while ((e = ast_walk_context_extensions(con, e)))
3990  ast_unlock_context(con);
3991  }
3993  }
3994 }
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:8530
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:292
const char * ast_get_context_name(struct ast_context *con)
Definition: ael_main.c:421
char lcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:293
struct ast_context * ast_walk_contexts(struct ast_context *con)
Definition: conf2ael.c:618
int ast_rdlock_contexts(void)
Read locks the context list.
Definition: pbx.c:8507
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
static void reschedule_precache(const char *number, const char *context, int expiration)
Definition: pbx_dundi.c:3937
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8512
const char * ast_get_extension_name(struct ast_exten *exten)
Definition: pbx.c:8548
#define LOG_NOTICE
Definition: logger.h:263
struct ast_exten * ast_walk_context_extensions(struct ast_context *con, struct ast_exten *priority)
Definition: ael_main.c:427
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284
int ast_rdlock_context(struct ast_context *con)
Read locks a given context.
Definition: pbx.c:8525

◆ dundi_precache_internal()

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

Definition at line 3996 of file pbx_dundi.c.

References ast_alloca, ast_copy_string(), ast_debug, AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log, ast_tvdiff_ms(), ast_tvnow(), ast_waitfor_n_fd(), build_transactions(), cancel_request(), dundi_request::dcontext, dundi_request::dr, dundi_cache_time, DUNDI_FLUFF_TIME, DUNDI_TTL_TIME, errno, dundi_request::expiration, dundi_request::hmd, permission::list, LOG_NOTICE, LOG_WARNING, MAX_RESULTS, dundi_request::maxcount, NULL, dundi_request::number, optimize_transactions(), dundi_request::pfds, precache_transactions(), reschedule_precache(), and dundi_request::trans.

Referenced by dundi_precache(), dundi_precache_thread(), and str2tech().

3997 {
3998  struct dundi_request dr;
3999  struct dundi_hint_metadata hmd;
4000  struct dundi_result dr2[MAX_RESULTS];
4001  struct timeval start;
4002  struct dundi_mapping *maps = NULL, *cur;
4003  int nummaps = 0;
4004  int foundanswers;
4005  int foundcache, skipped, ttlms, ms;
4006  if (!context)
4007  context = "e164";
4008  ast_debug(1, "Precache internal (%s@%s)!\n", number, context);
4009 
4010  AST_LIST_LOCK(&peers);
4011  AST_LIST_TRAVERSE(&mappings, cur, list) {
4012  if (!strcasecmp(cur->dcontext, context))
4013  nummaps++;
4014  }
4015  if (nummaps) {
4016  maps = ast_alloca(nummaps * sizeof(*maps));
4017  nummaps = 0;
4018  AST_LIST_TRAVERSE(&mappings, cur, list) {
4019  if (!strcasecmp(cur->dcontext, context))
4020  maps[nummaps++] = *cur;
4021  }
4022  }
4024  if (!nummaps) {
4025  return -1;
4026  }
4027  ttlms = DUNDI_FLUFF_TIME + ttl * DUNDI_TTL_TIME;
4028  memset(&dr2, 0, sizeof(dr2));
4029  memset(&dr, 0, sizeof(dr));
4030  memset(&hmd, 0, sizeof(hmd));
4031  dr.dr = dr2;
4032  ast_copy_string(dr.number, number, sizeof(dr.number));
4033  ast_copy_string(dr.dcontext, context ? context : "e164", sizeof(dr.dcontext));
4034  dr.maxcount = MAX_RESULTS;
4035  dr.expiration = dundi_cache_time;
4036  dr.hmd = &hmd;
4037  dr.pfds[0] = dr.pfds[1] = -1;
4038  if (pipe(dr.pfds) < 0) {
4039  ast_log(LOG_WARNING, "pipe() failed: %s\n", strerror(errno));
4040  return -1;
4041  }
4042  build_transactions(&dr, ttl, 0, &foundcache, &skipped, 0, 1, 1, NULL, avoids, NULL);
4044  foundanswers = 0;
4045  precache_transactions(&dr, maps, nummaps, &dr.expiration, &foundanswers);
4046  if (foundanswers) {
4047  if (dr.expiration > 0)
4048  reschedule_precache(dr.number, dr.dcontext, dr.expiration);
4049  else
4050  ast_log(LOG_NOTICE, "Weird, expiration = %d, but need to precache for %s@%s?!\n", dr.expiration, dr.number, dr.dcontext);
4051  }
4052  start = ast_tvnow();
4053  while (!AST_LIST_EMPTY(&dr.trans) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms)) {
4054  if (dr.pfds[0] > -1) {
4055  ms = 100;
4056  ast_waitfor_n_fd(dr.pfds, 1, &ms, NULL);
4057  } else
4058  usleep(1);
4059  }
4060  cancel_request(&dr);
4061  if (dr.pfds[0] > -1) {
4062  close(dr.pfds[0]);
4063  close(dr.pfds[1]);
4064  }
4065  return 0;
4066 }
static float dr[4]
Definition: tdd.c:58
#define DUNDI_FLUFF_TIME
Definition: dundi.h:211
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
static int precache_transactions(struct dundi_request *dr, struct dundi_mapping *maps, int mapcount, int *expiration, int *foundanswers)
Definition: pbx_dundi.c:3536
static int dundi_cache_time
Definition: pbx_dundi.c:196
#define LOG_WARNING
Definition: logger.h:274
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define MAX_RESULTS
Definition: pbx_dundi.c:153
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
struct dundi_mapping::@442 list
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
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
static void reschedule_precache(const char *number, const char *context, int expiration)
Definition: pbx_dundi.c:3937
#define DUNDI_TTL_TIME
Definition: dundi.h:212
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
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
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_precache_thread()

static void* dundi_precache_thread ( void *  data)
static

Definition at line 721 of file pbx_dundi.c.

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

Referenced by dundi_prop_precache().

722 {
723  struct dundi_query_state *st = data;
724  struct dundi_ie_data ied;
725  struct dundi_hint_metadata hmd = {0};
726  char eid_str[20];
727 
728  ast_debug(1, "Whee, precaching '%s@%s' for '%s'\n", st->called_number, st->called_context,
729  st->eids[0] ? ast_eid_to_str(eid_str, sizeof(eid_str), st->eids[0]) : "ourselves");
730  memset(&ied, 0, sizeof(ied));
731 
732  /* Now produce precache */
734 
736  /* Truncate if "don't ask" isn't present */
738  hmd.exten[0] = '\0';
739  if (ast_test_flag(st->trans, FLAG_DEAD)) {
740  ast_debug(1, "Our transaction went away!\n");
741  st->trans->thread = 0;
742  destroy_trans(st->trans, 0);
743  } else {
744  dundi_send(st->trans, DUNDI_COMMAND_PRECACHERP, 0, 1, &ied);
745  st->trans->thread = 0;
746  }
748  ast_free(st);
749  return NULL;
750 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
char called_number[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:548
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_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
dundi_eid * eids[DUNDI_MAX_STACK+1]
Definition: pbx_dundi.c:544
struct dundi_transaction * trans
Definition: pbx_dundi.c:552
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
static void destroy_trans(struct dundi_transaction *trans, int fromtimeout)
Definition: pbx_dundi.c:3203
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_free(a)
Definition: astmm.h:182
char exten[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:233
static int dundi_precache_internal(const char *context, const char *number, int ttl, dundi_eid *avoids[])
Definition: pbx_dundi.c:3996
#define DUNDI_COMMAND_PRECACHERP
Definition: dundi.h:165
#define ast_test_flag_nonstd(p, flag)
Definition: utils.h:173
char called_context[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:547

◆ dundi_prop_precache()

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

Definition at line 940 of file pbx_dundi.c.

References dundi_ies::anscount, dundi_ies::answers, ast_calloc, ast_clear_flag_nonstd, ast_copy_string(), ast_debug, ast_eid_cmp(), ast_eid_to_str(), ast_free, AST_LIST_TRAVERSE, ast_log, ast_pthread_create_detached, cache_save(), cache_save_hint(), dundi_ies::called_context, dundi_query_state::called_context, dundi_ies::called_number, dundi_query_state::called_number, dundi_ies::cbypass, dundi_answer::data, dundi_request::dcontext, dundi_mapping::dcontext, dundi_result::dest, dundi_query_state::directs, dr, dundi_request::dr, dundi_cache_time, DUNDI_CAUSE_GENERAL, DUNDI_COMMAND_PRECACHERP, DUNDI_HINT_DONT_ASK, DUNDI_HINT_UNAFFECTED, dundi_ie_append_cause(), DUNDI_IE_CAUSE, dundi_precache_thread(), dundi_send(), dundi_answer::eid, dundi_result::eid, dundi_ies::eid_direct, dundi_result::eid_str, dundi_ies::eidcount, dundi_ies::eids, dundi_query_state::eids, dundi_ies::expiration, dundi_result::expiration, dundi_request::expiration, dundi_answer::flags, dundi_result::flags, dundi_hint_metadata::flags, dundi_query_state::fluffy, dundi_ies::hint, dundi_request::hmd, permission::list, dundi_mapping::list, LOG_NOTICE, LOG_WARNING, dundi_query_state::maps, MAX_RESULTS, dundi_request::maxcount, dundi_mapping::next, dundi_query_state::nocache, NULL, dundi_request::number, dundi_query_state::nummaps, dundi_transaction::parent, dundi_request::pfds, dundi_answer::protocol, dundi_request::respcount, dundi_result::tech, tech2str(), dundi_result::techint, dundi_transaction::them_eid, dundi_transaction::thread, dundi_query_state::trans, dundi_ies::ttl, dundi_query_state::ttl, dundi_answer::weight, and dundi_result::weight.

Referenced by handle_command_response().

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

◆ dundi_query()

static int dundi_query ( struct dundi_transaction trans)
static

Definition at line 3503 of file pbx_dundi.c.

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

Referenced by query_transactions().

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

◆ dundi_query_eid()

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

Retrieve information on a specific EID.

Definition at line 4121 of file pbx_dundi.c.

References dundi_query_eid_internal(), and NULL.

Referenced by dundi_do_query().

4122 {
4123  dundi_eid *avoid[1] = { NULL, };
4124  struct dundi_hint_metadata hmd;
4125  memset(&hmd, 0, sizeof(hmd));
4126  return dundi_query_eid_internal(dei, dcontext, &eid, &hmd, dundi_ttl, 0, avoid);
4127 }
#define NULL
Definition: resample.c:96
An Entity ID is essentially a MAC address, brief and unique.
Definition: utils.h:786
static int dundi_query_eid_internal(struct dundi_entity_info *dei, const char *dcontext, dundi_eid *eid, struct dundi_hint_metadata *hmd, int ttl, int blockempty, dundi_eid *avoid[])
Definition: pbx_dundi.c:4074
static int dundi_ttl
Definition: pbx_dundi.c:194

◆ dundi_query_eid_internal()

static int dundi_query_eid_internal ( struct dundi_entity_info dei,
const char *  dcontext,
dundi_eid eid,
struct dundi_hint_metadata hmd,
int  ttl,
int  blockempty,
dundi_eid avoid[] 
)
static

Definition at line 4074 of file pbx_dundi.c.

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

Referenced by dundi_precache_thread(), dundi_query_eid(), and dundi_query_thread().

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

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

Definition at line 4215 of file pbx_dundi.c.

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

4216 {
4221  );
4222  struct ast_flags opts = { 0, };
4223  char *parse;
4224  struct dundi_result_datastore *drds;
4225  struct ast_datastore *datastore;
4226 
4227  if (ast_strlen_zero(data)) {
4228  ast_log(LOG_WARNING, "DUNDIQUERY requires an argument (number)\n");
4229  return -1;
4230  }
4231 
4232  if (!chan) {
4233  ast_log(LOG_ERROR, "DUNDIQUERY can not be used without a channel!\n");
4234  return -1;
4235  }
4236 
4237  parse = ast_strdupa(data);
4238 
4239  AST_STANDARD_APP_ARGS(args, parse);
4240 
4241  if (!ast_strlen_zero(args.options))
4242  ast_app_parse_options(dundi_query_opts, &opts, NULL, args.options);
4243 
4244  if (ast_strlen_zero(args.context))
4245  args.context = "e164";
4246 
4247  if (!(drds = ast_calloc(1, sizeof(*drds)))) {
4248  return -1;
4249  }
4250 
4251  drds->id = ast_atomic_fetchadd_int((int *) &dundi_result_id, 1);
4252  snprintf(buf, len, "%u", drds->id);
4253 
4254  if (!(datastore = ast_datastore_alloc(&dundi_result_datastore_info, buf))) {
4255  drds_destroy(drds);
4256  return -1;
4257  }
4258 
4259  datastore->data = drds;
4260 
4261  drds->num_results = dundi_lookup(drds->results, ARRAY_LEN(drds->results), NULL, args.context,
4262  args.number, ast_test_flag(&opts, OPT_BYPASS_CACHE));
4263 
4264  if (drds->num_results > 0)
4265  sort_results(drds->results, drds->num_results);
4266 
4267  ast_channel_lock(chan);
4268  ast_channel_datastore_add(chan, datastore);
4269  ast_channel_unlock(chan);
4270 
4271  return 0;
4272 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
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 ARRAY_LEN(a)
Definition: isdn_lib.c:42
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
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define LOG_WARNING
Definition: logger.h:274
Structure for a data store object.
Definition: datastore.h:68
const char * args
#define NULL
Definition: resample.c:96
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:755
#define ast_strlen_zero(foo)
Definition: strings.h:52
Number structure.
Definition: app_followme.c:154
#define ast_log
Definition: astobj2.c:42
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:2906
static unsigned int dundi_result_id
Definition: pbx_dundi.c:4191
#define LOG_ERROR
Definition: logger.h:285
static const struct ast_datastore_info dundi_result_datastore_info
Definition: pbx_dundi.c:4210
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define ast_channel_unlock(chan)
Definition: channel.h:2946
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
Structure used to handle boolean flags.
Definition: utils.h:199
void * data
Definition: datastore.h:70
struct dundi_result results[MAX_RESULTS]
Definition: pbx_dundi.c:4194
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:89
static struct test_options options
static const struct ast_app_option dundi_query_opts[128]
Definition: pbx_dundi.c:4135
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2390
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.
static void drds_destroy(struct dundi_result_datastore *drds)
Definition: pbx_dundi.c:4199

◆ dundi_query_thread()

static void* dundi_query_thread ( void *  data)
static

Definition at line 754 of file pbx_dundi.c.

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

Referenced by dundi_answer_entity().

755 {
756  struct dundi_query_state *st = data;
757  struct dundi_entity_info dei;
758  struct dundi_ie_data ied;
759  struct dundi_hint_metadata hmd;
760  char eid_str[20];
761  int res;
762 
763  ast_debug(1, "Whee, looking up '%s@%s' for '%s'\n", st->called_number, st->called_context,
764  st->eids[0] ? ast_eid_to_str(eid_str, sizeof(eid_str), st->eids[0]) : "ourselves");
765  memset(&ied, 0, sizeof(ied));
766  memset(&dei, 0, sizeof(dei));
767  memset(&hmd, 0, sizeof(hmd));
768  if (!ast_eid_cmp(&st->trans->us_eid, &st->reqeid)) {
769  /* Ooh, it's us! */
770  ast_debug(1, "Neat, someone look for us!\n");
771  ast_copy_string(dei.orgunit, dept, sizeof(dei.orgunit));
772  ast_copy_string(dei.org, org, sizeof(dei.org));
773  ast_copy_string(dei.locality, locality, sizeof(dei.locality));
774  ast_copy_string(dei.stateprov, stateprov, sizeof(dei.stateprov));
775  ast_copy_string(dei.country, country, sizeof(dei.country));
776  ast_copy_string(dei.email, email, sizeof(dei.email));
777  ast_copy_string(dei.phone, phone, sizeof(dei.phone));
778  res = 1;
779  } else {
780  /* If we do not have a canonical result, keep looking */
781  res = dundi_query_eid_internal(&dei, st->called_context, &st->reqeid, &hmd, st->ttl, 1, st->eids);
782  }
784  if (ast_test_flag(st->trans, FLAG_DEAD)) {
785  ast_debug(1, "Our transaction went away!\n");
786  st->trans->thread = 0;
787  destroy_trans(st->trans, 0);
788  } else {
789  if (res) {
790  dundi_ie_append_str(&ied, DUNDI_IE_DEPARTMENT, dei.orgunit);
792  dundi_ie_append_str(&ied, DUNDI_IE_LOCALITY, dei.locality);
793  dundi_ie_append_str(&ied, DUNDI_IE_STATE_PROV, dei.stateprov);
794  dundi_ie_append_str(&ied, DUNDI_IE_COUNTRY, dei.country);
795  dundi_ie_append_str(&ied, DUNDI_IE_EMAIL, dei.email);
796  dundi_ie_append_str(&ied, DUNDI_IE_PHONE, dei.phone);
797  if (!ast_strlen_zero(dei.ipaddr))
798  dundi_ie_append_str(&ied, DUNDI_IE_IPADDR, dei.ipaddr);
799  }
800  dundi_ie_append_hint(&ied, DUNDI_IE_HINT, hmd.flags, hmd.exten);
801  dundi_send(st->trans, DUNDI_COMMAND_EIDRESPONSE, 0, 1, &ied);
802  st->trans->thread = 0;
803  }
805  ast_free(st);
806  return NULL;
807 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
char called_number[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:548
static char locality[80]
Definition: pbx_dundi.c:203
#define DUNDI_IE_IPADDR
Definition: dundi.h:206
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_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
dundi_eid * eids[DUNDI_MAX_STACK+1]
Definition: pbx_dundi.c:544
struct dundi_transaction * trans
Definition: pbx_dundi.c:552
static char email[80]
Definition: pbx_dundi.c:206
static char phone[80]
Definition: pbx_dundi.c:207
#define DUNDI_IE_EMAIL
Definition: dundi.h:204
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
int dundi_ie_append_hint(struct dundi_ie_data *ied, unsigned char ie, unsigned short flags, char *data)
Definition: dundi-parser.c:518
#define NULL
Definition: resample.c:96
dundi_eid us_eid
Definition: pbx_dundi.c:250
static void destroy_trans(struct dundi_transaction *trans, int fromtimeout)
Definition: pbx_dundi.c:3203
#define DUNDI_IE_DEPARTMENT
Definition: dundi.h:199
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
Definition: main/utils.c:2842
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define DUNDI_IE_LOCALITY
Definition: dundi.h:201
static int dundi_query_eid_internal(struct dundi_entity_info *dei, const char *dcontext, dundi_eid *eid, struct dundi_hint_metadata *hmd, int ttl, int blockempty, dundi_eid *avoid[])
Definition: pbx_dundi.c:4074
#define DUNDI_IE_PHONE
Definition: dundi.h:205
int dundi_ie_append_str(struct dundi_ie_data *ied, unsigned char ie, char *str)
Definition: dundi-parser.c:605
static char country[80]
Definition: pbx_dundi.c:205
#define DUNDI_IE_ORGANIZATION
Definition: dundi.h:200
#define DUNDI_IE_HINT
Definition: dundi.h:197
#define ast_free(a)
Definition: astmm.h:182
#define DUNDI_COMMAND_EIDRESPONSE
Definition: dundi.h:163
#define DUNDI_IE_STATE_PROV
Definition: dundi.h:202
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static char org[80]
Definition: pbx_dundi.c:202
#define DUNDI_IE_COUNTRY
Definition: dundi.h:203
char called_context[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:547
static char dept[80]
Definition: pbx_dundi.c:201
static char stateprov[80]
Definition: pbx_dundi.c:204

◆ dundi_reject()

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

Definition at line 455 of file pbx_dundi.c.

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

Referenced by handle_frame().

456 {
457  struct {
458  struct dundi_packet pack;
459  struct dundi_hdr hdr;
460  } tmp;
461  struct dundi_transaction trans;
462  /* Never respond to an INVALID with another INVALID */
463  if (h->cmdresp == DUNDI_COMMAND_INVALID)
464  return;
465  memset(&tmp, 0, sizeof(tmp));
466  memset(&trans, 0, sizeof(trans));
467  ast_sockaddr_copy(&trans.addr, sin);
468  tmp.hdr.strans = h->dtrans;
469  tmp.hdr.dtrans = h->strans;
470  tmp.hdr.iseqno = h->oseqno;
471  tmp.hdr.oseqno = h->iseqno;
472  tmp.hdr.cmdresp = DUNDI_COMMAND_INVALID;
473  tmp.hdr.cmdflags = 0;
474  tmp.pack.h = (struct dundi_hdr *)tmp.pack.data;
475  tmp.pack.datalen = sizeof(struct dundi_hdr);
476  tmp.pack.parent = &trans;
477  dundi_xmit(&tmp.pack);
478 }
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
static int tmp()
Definition: bt_open.c:389
unsigned char cmdresp
Definition: dundi.h:39
unsigned char oseqno
Definition: dundi.h:38
unsigned short strans
Definition: dundi.h:35
#define DUNDI_COMMAND_INVALID
Definition: dundi.h:166
unsigned short dtrans
Definition: dundi.h:36
unsigned char iseqno
Definition: dundi.h:37
static int dundi_xmit(struct dundi_packet *pack)
Definition: pbx_dundi.c:3169

◆ dundi_result_read()

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

Definition at line 4279 of file pbx_dundi.c.

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

4280 {
4282  AST_APP_ARG(id);
4283  AST_APP_ARG(resultnum);
4284  );
4285  char *parse;
4286  unsigned int num;
4287  struct dundi_result_datastore *drds;
4288  struct ast_datastore *datastore;
4289  int res = -1;
4290 
4291  if (ast_strlen_zero(data)) {
4292  ast_log(LOG_WARNING, "DUNDIRESULT requires an argument (id and resultnum)\n");
4293  goto finish;
4294  }
4295 
4296  if (!chan) {
4297  ast_log(LOG_ERROR, "DUNDRESULT can not be used without a channel!\n");
4298  goto finish;
4299  }
4300 
4301  parse = ast_strdupa(data);
4302 
4303  AST_STANDARD_APP_ARGS(args, parse);
4304 
4305  if (ast_strlen_zero(args.id)) {
4306  ast_log(LOG_ERROR, "A result ID must be provided to DUNDIRESULT\n");
4307  goto finish;
4308  }
4309 
4310  if (ast_strlen_zero(args.resultnum)) {
4311  ast_log(LOG_ERROR, "A result number must be given to DUNDIRESULT!\n");
4312  goto finish;
4313  }
4314 
4315  ast_channel_lock(chan);
4317  ast_channel_unlock(chan);
4318 
4319  if (!datastore) {
4320  ast_log(LOG_WARNING, "No DUNDi results found for query ID '%s'\n", args.id);
4321  goto finish;
4322  }
4323 
4324  drds = datastore->data;
4325 
4326  if (!strcasecmp(args.resultnum, "getnum")) {
4327  snprintf(buf, len, "%d", drds->num_results < 0 ? 0 : drds->num_results);
4328  res = 0;
4329  goto finish;
4330  }
4331 
4332  if (sscanf(args.resultnum, "%30u", &num) != 1) {
4333  ast_log(LOG_ERROR, "Invalid value '%s' for resultnum to DUNDIRESULT!\n",
4334  args.resultnum);
4335  goto finish;
4336  }
4337 
4338  if (num && drds->num_results > 0 && num <= drds->num_results) {
4339  snprintf(buf, len, "%s/%s", drds->results[num - 1].tech, drds->results[num - 1].dest);
4340  res = 0;
4341  } else
4342  ast_log(LOG_WARNING, "Result number %u is not valid for DUNDi query results for ID %s!\n", num, args.id);
4343 
4344 finish:
4345  return res;
4346 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define LOG_WARNING
Definition: logger.h:274
char dest[256]
Definition: dundi.h:233
Structure for a data store object.
Definition: datastore.h:68
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2404
const char * args
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
char tech[10]
Definition: dundi.h:232
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define LOG_ERROR
Definition: logger.h:285
static const struct ast_datastore_info dundi_result_datastore_info
Definition: pbx_dundi.c:4210
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define ast_channel_unlock(chan)
Definition: channel.h:2946
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
void * data
Definition: datastore.h:70
struct dundi_result results[MAX_RESULTS]
Definition: pbx_dundi.c:4194
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

◆ dundi_rexmit()

static int dundi_rexmit ( const void *  data)
static

Definition at line 3285 of file pbx_dundi.c.

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

Referenced by dundi_send().

3286 {
3287  struct dundi_packet *pack = (struct dundi_packet *)data;
3288  int res;
3289  AST_LIST_LOCK(&peers);
3290  if (pack->retrans < 1) {
3291  pack->retransid = -1;
3292  if (!ast_test_flag(pack->parent, FLAG_ISQUAL)) {
3293  ast_log(LOG_NOTICE, "Max retries exceeded to host '%s' msg %d on call %d\n",
3294  ast_sockaddr_stringify(&pack->parent->addr), pack->h->oseqno, ntohs(pack->h->strans));
3295  }
3296  destroy_trans(pack->parent, 1);
3297  res = 0;
3298  } else {
3299  /* Decrement retransmission, try again */
3300  pack->retrans--;
3301  dundi_xmit(pack);
3302  res = 1;
3303  }
3305  return res;
3306 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
unsigned char oseqno
Definition: dundi.h:38
static void destroy_trans(struct dundi_transaction *trans, int fromtimeout)
Definition: pbx_dundi.c:3203
unsigned char data[0]
Definition: pbx_dundi.c:228
#define ast_log
Definition: astobj2.c:42
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
#define LOG_NOTICE
Definition: logger.h:263
unsigned short strans
Definition: dundi.h:35
struct dundi_transaction * parent
Definition: pbx_dundi.c:225
struct ast_sockaddr addr
Definition: pbx_dundi.c:246
struct dundi_hdr * h
Definition: pbx_dundi.c:223
static int dundi_xmit(struct dundi_packet *pack)
Definition: pbx_dundi.c:3169

◆ dundi_send()

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

Definition at line 3308 of file pbx_dundi.c.

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

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

3309 {
3310  struct dundi_packet *pack;
3311  int res;
3312  int len;
3313  char eid_str[20];
3314  len = sizeof(struct dundi_packet) + sizeof(struct dundi_hdr) + (ied ? ied->pos : 0);
3315  /* Reserve enough space for encryption */
3316  if (ast_test_flag(trans, FLAG_ENCRYPT))
3317  len += 384;
3318  pack = ast_calloc(1, len);
3319  if (pack) {
3320  pack->h = (struct dundi_hdr *)(pack->data);
3321  pack->retransid = -1;
3322  if (cmdresp != DUNDI_COMMAND_ACK) {
3323  pack->retransid = ast_sched_add(sched, trans->retranstimer, dundi_rexmit, pack);
3324  pack->retrans = DUNDI_DEFAULT_RETRANS - 1;
3325  AST_LIST_INSERT_HEAD(&trans->packets, pack, list);
3326  }
3327  pack->parent = trans;
3328  pack->h->strans = htons(trans->strans);
3329  pack->h->dtrans = htons(trans->dtrans);
3330  pack->h->iseqno = trans->iseqno;
3331  pack->h->oseqno = trans->oseqno;
3332  pack->h->cmdresp = cmdresp;
3333  pack->datalen = sizeof(struct dundi_hdr);
3334  if (ied) {
3335  memcpy(pack->h->ies, ied->buf, ied->pos);
3336  pack->datalen += ied->pos;
3337  }
3338  if (final) {
3339  pack->h->cmdresp |= DUNDI_COMMAND_FINAL;
3340  ast_set_flag(trans, FLAG_FINAL);
3341  }
3342  pack->h->cmdflags = flags;
3343  if (cmdresp != DUNDI_COMMAND_ACK) {
3344  trans->oseqno++;
3345  trans->oseqno = trans->oseqno % 256;
3346  }
3347  trans->aseqno = trans->iseqno;
3348  /* If we have their public key, encrypt */
3349  if (ast_test_flag(trans, FLAG_ENCRYPT)) {
3350  switch(cmdresp) {
3351  case DUNDI_COMMAND_REGREQ:
3359  if (dundidebug)
3360  dundi_showframe(pack->h, 2, &trans->addr, pack->datalen - sizeof(struct dundi_hdr));
3361  res = dundi_encrypt(trans, pack);
3362  break;
3363  default:
3364  res = 0;
3365  }
3366  } else
3367  res = 0;
3368  if (!res)
3369  res = dundi_xmit(pack);
3370  if (res)
3371  ast_log(LOG_NOTICE, "Failed to send packet to '%s'\n", ast_eid_to_str(eid_str, sizeof(eid_str), &trans->them_eid));
3372 
3373  if (cmdresp == DUNDI_COMMAND_ACK)
3374  ast_free(pack);
3375  return res;
3376  }
3377  return -1;
3378 }
#define DUNDI_DEFAULT_RETRANS
Definition: dundi.h:214
unsigned char aseqno
Definition: pbx_dundi.c:265
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_set_flag(p, flag)
Definition: utils.h:70
Definition: sched.c:76
if(!yyg->yy_init)
Definition: ast_expr2f.c:868
unsigned char cmdresp
Definition: dundi.h:39
unsigned char oseqno
Definition: dundi.h:38
dundi_eid them_eid
Definition: pbx_dundi.c:251
#define DUNDI_COMMAND_ACK
Definition: dundi.h:159
unsigned char data[0]
Definition: pbx_dundi.c:228
unsigned char buf[8192]
Definition: dundi-parser.h:56
#define DUNDI_COMMAND_DPRESPONSE
Definition: dundi.h:161
#define ast_log
Definition: astobj2.c:42
static int dundidebug
Definition: pbx_dundi.c:192
unsigned char cmdflags
Definition: dundi.h:40
struct dundi_packet::@436 list
struct dundi_transaction::packetlist packets
unsigned char ies[0]
Definition: dundi.h:41
unsigned short strans
Definition: pbx_dundi.c:260
static int dundi_rexmit(const void *data)
Definition: pbx_dundi.c:3285
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
unsigned char oseqno
Definition: pbx_dundi.c:264
#define LOG_NOTICE
Definition: logger.h:263
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
unsigned short dtrans
Definition: pbx_dundi.c:261
#define ast_free(a)
Definition: astmm.h:182
unsigned short strans
Definition: dundi.h:35
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
void dundi_showframe(struct dundi_hdr *fhi, int rx, struct ast_sockaddr *sin, int datalen)
Definition: dundi-parser.c:432
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_PRECACHERQ
Definition: dundi.h:164
#define DUNDI_COMMAND_PRECACHERP
Definition: dundi.h:165
#define DUNDI_COMMAND_REGREQ
Definition: dundi.h:169
#define DUNDI_COMMAND_FINAL
Definition: dundi.h:157
#define DUNDI_COMMAND_EIDRESPONSE
Definition: dundi.h:163
static int dundi_encrypt(struct dundi_transaction *trans, struct dundi_packet *pack)
Definition: pbx_dundi.c:1428
#define DUNDI_COMMAND_EIDQUERY
Definition: dundi.h:162
#define DUNDI_COMMAND_DPDISCOVER
Definition: dundi.h:160
unsigned short dtrans
Definition: dundi.h:36
unsigned char iseqno
Definition: pbx_dundi.c:262
struct dundi_transaction * parent
Definition: pbx_dundi.c:225
struct ast_sockaddr addr
Definition: pbx_dundi.c:246
struct dundi_hdr * h
Definition: pbx_dundi.c:223
#define DUNDI_COMMAND_REGRESPONSE
Definition: dundi.h:170
unsigned char iseqno
Definition: dundi.h:37
static int dundi_xmit(struct dundi_packet *pack)
Definition: pbx_dundi.c:3169

◆ dundi_set_debug()

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

Definition at line 2304 of file pbx_dundi.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, NULL, and ast_cli_entry::usage.

2305 {
2306  switch (cmd) {
2307  case CLI_INIT:
2308  e->command = "dundi set debug {on|off}";
2309  e->usage =
2310  "Usage: dundi set debug {on|off}\n"
2311  " Enables/Disables dumping of DUNDi packets for debugging purposes\n";
2312  return NULL;
2313  case CLI_GENERATE:
2314  return NULL;
2315  }
2316 
2317  if (a->argc != e->args) {
2318  return CLI_SHOWUSAGE;
2319  }
2320  if (!strncasecmp(a->argv[e->args -1], "on", 2)) {
2321  dundidebug = 1;
2322  ast_cli(a->fd, "DUNDi Debugging Enabled\n");
2323  } else {
2324  dundidebug = 0;
2325  ast_cli(a->fd, "DUNDi Debugging Disabled\n");
2326  }
2327  return CLI_SUCCESS;
2328 }
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
int args
This gets set in ast_cli_register()
Definition: cli.h:185
const int fd
Definition: cli.h:159
static int dundidebug
Definition: pbx_dundi.c:192
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

◆ dundi_show_cache()

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

Definition at line 2955 of file pbx_dundi.c.

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

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

◆ dundi_show_entityid()

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

Definition at line 2827 of file pbx_dundi.c.

References ast_cli_args::argc, ast_cli(), ast_eid_to_str(), AST_LIST_LOCK, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, NULL, and ast_cli_entry::usage.

2828 {
2829  char eid_str[20];
2830  switch (cmd) {
2831  case CLI_INIT:
2832  e->command = "dundi show entityid";
2833  e->usage =
2834  "Usage: dundi show entityid\n"
2835  " Displays the global entityid for this host.\n";
2836  return NULL;
2837  case CLI_GENERATE:
2838  return NULL;
2839  }
2840  if (a->argc != 3) {
2841  return CLI_SHOWUSAGE;
2842  }
2843  AST_LIST_LOCK(&peers);
2844  ast_eid_to_str(eid_str, sizeof(eid_str), &global_eid);
2846  ast_cli(a->fd, "Global EID for this system is '%s'\n", eid_str);
2847  return CLI_SUCCESS;
2848 }
#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
static dundi_eid global_eid
Definition: pbx_dundi.c:198
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
#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
#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

◆ dundi_show_hints()

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

Definition at line 3050 of file pbx_dundi.c.

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

3051 {
3052 #define FORMAT2 "%-12.12s %-16.16s %-10.10s %-18s\n"
3053 #define FORMAT "%-12.12s %-16.16s %6d sec %-18s\n"
3054  struct ast_db_entry *db_tree, *db_entry;
3055  int cnt = 0;
3056  time_t ts, now;
3057  dundi_eid src_eid;
3058  char src_eid_str[20];
3059  int expiry;
3060  int length;
3061  char *ptr, *src, *number, *context;
3062 
3063  switch (cmd) {
3064  case CLI_INIT:
3065  e->command = "dundi show hints";
3066  e->usage =
3067  "Usage: dundi show hints\n"
3068  " Lists all DUNDi 'DONTASK' hints in the cache.\n";
3069  return NULL;
3070  case CLI_GENERATE:
3071  return NULL;
3072  }
3073 
3074  if (a->argc != 3) {
3075  return CLI_SHOWUSAGE;
3076  }
3077 
3078  time(&now);
3079  db_tree = ast_db_gettree("dundi/cache/hint", NULL);
3080  ast_cli(a->fd, FORMAT2, "Prefix", "Context", "Expiration", "From");
3081 
3082  for (db_entry = db_tree; db_entry; db_entry = db_entry->next) {
3083  char *rest = NULL;
3084 
3085  if (ast_get_time_t(db_entry->data, &ts, 0, &length)) {
3086  continue;
3087  }
3088 
3089  expiry = ts - now;
3090 
3091  if (expiry <= 0) {
3092  continue;
3093  }
3094 
3095  ptr = db_entry->key + sizeof("/dundi/cache/hint");
3096  src = strtok_r(ptr, "/", &rest);
3097  number = strtok_r(NULL, "/", &rest);
3098  context = strtok_r(NULL, "/", &rest);
3099  ptr = strtok_r(NULL, "/", &rest);
3100 
3101  if (*ptr != 'e') {
3102  continue;
3103  }
3104 
3105  cnt++;
3106  dundi_str_short_to_eid(&src_eid, src);
3107  ast_eid_to_str(src_eid_str, sizeof(src_eid_str), &src_eid);
3108  ast_cli(a->fd, FORMAT, number, context, expiry, src_eid_str);
3109  }
3110 
3111  ast_cli(a->fd, "Number of entries: %d\n", cnt);
3112  ast_db_freetree(db_tree);
3113 
3114  return CLI_SUCCESS;
3115 #undef FORMAT
3116 #undef FORMAT2
3117 }
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
Definition: main/utils.c:2587
const int argc
Definition: cli.h:160
void ast_db_freetree(struct ast_db_entry *entry)
Free structure created by ast_db_gettree()
Definition: main/db.c:598
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
Number structure.
Definition: app_followme.c:154
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
struct ast_db_entry * next
Definition: astdb.h:32
const int fd
Definition: cli.h:159
struct ast_db_entry * ast_db_gettree(const char *family, const char *keytree)
Get a list of values within the astdb tree.
Definition: main/db.c:531
#define CLI_SHOWUSAGE
Definition: cli.h:45
Definition: astdb.h:31
char data[0]
Definition: astdb.h:34
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
#define FORMAT
#define FORMAT2
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
int dundi_str_short_to_eid(dundi_eid *eid, const char *s)
Definition: dundi-parser.c:70
char * key
Definition: astdb.h:33

◆ dundi_show_mappings()

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

Definition at line 2883 of file pbx_dundi.c.

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

2884 {
2885 #define FORMAT2 "%-12.12s %-7.7s %-12.12s %-10.10s %-5.5s %-25.25s\n"
2886 #define FORMAT "%-12.12s %-7s %-12.12s %-10.10s %-5.5s %-25.25s\n"
2887  struct dundi_mapping *map;
2888  char fs[256];
2889  char weight[8];
2890  switch (cmd) {
2891  case CLI_INIT:
2892  e->command = "dundi show mappings";
2893  e->usage =
2894  "Usage: dundi show mappings\n"
2895  " Lists all known DUNDi mappings.\n";
2896  return NULL;
2897  case CLI_GENERATE:
2898  return NULL;
2899  }
2900  if (a->argc != 3) {
2901  return CLI_SHOWUSAGE;
2902  }
2903  AST_LIST_LOCK(&peers);
2904  ast_cli(a->fd, FORMAT2, "DUNDi Cntxt", "Weight", "Local Cntxt", "Options", "Tech", "Destination");
2905  AST_LIST_TRAVERSE(&mappings, map, list) {
2906  snprintf(weight, sizeof(weight), "%d", get_mapping_weight(map, NULL));
2907  ast_cli(a->fd, FORMAT, map->dcontext, weight,
2908  ast_strlen_zero(map->lcontext) ? "<none>" : map->lcontext,
2909  dundi_flags2str(fs, sizeof(fs), map->options), tech2str(map->tech), map->dest);
2910  }
2912  return CLI_SUCCESS;
2913 #undef FORMAT
2914 #undef FORMAT2
2915 }
char dest[512]
Definition: pbx_dundi.c:299
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
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
static char * tech2str(int tech)
Definition: pbx_dundi.c:380
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
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
struct dundi_mapping::@442 list
#define ast_strlen_zero(foo)
Definition: strings.h:52
const int fd
Definition: cli.h:159
#define CLI_SHOWUSAGE
Definition: cli.h:45
char weight
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
static int get_mapping_weight(struct dundi_mapping *map, struct varshead *headp)
Definition: pbx_dundi.c:559
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
#define FORMAT
#define FORMAT2
char * dundi_flags2str(char *buf, int bufsiz, int flags)
Definition: dundi-parser.c:246

◆ dundi_show_peer()

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

Definition at line 2621 of file pbx_dundi.c.

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

2622 {
2623  struct dundi_peer *peer;
2624  struct permission *p;
2625  char *order;
2626  char eid_str[20];
2627  int x, cnt;
2628  switch (cmd) {
2629  case CLI_INIT:
2630  e->command = "dundi show peer";
2631  e->usage =
2632  "Usage: dundi show peer [peer]\n"
2633  " Provide a detailed description of a specifid DUNDi peer.\n";
2634  return NULL;
2635  case CLI_GENERATE:
2636  return complete_peer_helper(a->line, a->word, a->pos, a->n, 3);
2637  }
2638  if (a->argc != 4) {
2639  return CLI_SHOWUSAGE;
2640  }
2641  AST_LIST_LOCK(&peers);
2642  AST_LIST_TRAVERSE(&peers, peer, list) {
2643  if (!strcasecmp(ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), a->argv[3]))
2644  break;
2645  }
2646  if (peer) {
2647  switch(peer->order) {
2648  case 0:
2649  order = "Primary";
2650  break;
2651  case 1:
2652  order = "Secondary";
2653  break;
2654  case 2:
2655  order = "Tertiary";
2656  break;
2657  case 3:
2658  order = "Quartiary";
2659  break;
2660  default:
2661  order = "Unknown";
2662  }
2663  ast_cli(a->fd, "Peer: %s\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
2664  ast_cli(a->fd, "Model: %s\n", model2str(peer->model));
2665  ast_cli(a->fd, "Order: %s\n", order);
2666  ast_cli(a->fd, "Host: %s\n", ast_sockaddr_isnull(&peer->addr) ? "<Unspecified>" : ast_sockaddr_stringify_host(&peer->addr));
2667  ast_cli(a->fd, "Port: %d\n", dundi_sockaddr_port(&peer->addr));
2668  ast_cli(a->fd, "Dynamic: %s\n", peer->dynamic ? "yes" : "no");
2669  ast_cli(a->fd, "Reg: %s\n", peer->registerid < 0 ? "No" : "Yes");
2670  ast_cli(a->fd, "In Key: %s\n", ast_strlen_zero(peer->inkey) ? "<None>" : peer->inkey);
2671  ast_cli(a->fd, "Out Key: %s\n", ast_strlen_zero(peer->outkey) ? "<None>" : peer->outkey);
2672  if (!AST_LIST_EMPTY(&peer->include))
2673  ast_cli(a->fd, "Include logic%s:\n", peer->model & DUNDI_MODEL_OUTBOUND ? "" : " (IGNORED)");
2674  AST_LIST_TRAVERSE(&peer->include, p, list)
2675  ast_cli(a->fd, "-- %s %s\n", p->allow ? "include" : "do not include", p->name);
2676  if (!AST_LIST_EMPTY(&peer->permit))
2677  ast_cli(a->fd, "Query logic%s:\n", peer->model & DUNDI_MODEL_INBOUND ? "" : " (IGNORED)");
2678  AST_LIST_TRAVERSE(&peer->permit, p, list)
2679  ast_cli(a->fd, "-- %s %s\n", p->allow ? "permit" : "deny", p->name);
2680  cnt = 0;
2681  for (x = 0;x < DUNDI_TIMING_HISTORY; x++) {
2682  if (peer->lookups[x]) {
2683  if (!cnt)
2684  ast_cli(a->fd, "Last few query times:\n");
2685  ast_cli(a->fd, "-- %d. %s (%d ms)\n", x + 1, peer->lookups[x], peer->lookuptimes[x]);
2686  cnt++;
2687  }
2688  }
2689  if (cnt)
2690  ast_cli(a->fd, "Average query time: %d ms\n", peer->avgms);
2691  } else
2692  ast_cli(a->fd, "No such peer '%s'\n", a->argv[3]);
2694  return CLI_SUCCESS;
2695 }
static char * complete_peer_helper(const char *line, const char *word, int pos, int state, int rpos)
Definition: pbx_dundi.c:2417
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
char * lookups[DUNDI_TIMING_HISTORY]
Definition: pbx_dundi.c:327
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 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
#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
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 char * line
Definition: cli.h:162
#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
int registerid
Definition: pbx_dundi.c:312
const int fd
Definition: cli.h:159
integer order
Definition: analys.c:66
const int n
Definition: cli.h:165
#define DUNDI_MODEL_INBOUND
Definition: pbx_dundi.c:159
static uint16_t dundi_sockaddr_port(const struct ast_sockaddr *addr)
Definition: pbx_dundi.c:2609
const char *const * argv
Definition: cli.h:161
unsigned int dynamic
Definition: pbx_dundi.c:334
#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
char * command
Definition: cli.h:186
dundi_eid eid
Definition: pbx_dundi.c:304
const char * word
Definition: cli.h:163
char inkey[80]
Definition: pbx_dundi.c:309
struct dundi_peer::permissionlist permit
char name[0]
Definition: pbx_dundi.c:218
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
struct permissionlist include
Definition: pbx_dundi.c:307
const int pos
Definition: cli.h:164
struct ast_sockaddr addr
Definition: pbx_dundi.c:305
#define DUNDI_MODEL_OUTBOUND
Definition: pbx_dundi.c:160
static char * model2str(int model)
Definition: pbx_dundi.c:2403
struct permission::@435 list
static char * ast_sockaddr_stringify_host(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only, suitable for a URL (with brack...
Definition: netsock2.h:331

◆ dundi_show_peers()

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

Definition at line 2697 of file pbx_dundi.c.

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

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

◆ dundi_show_precache()

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

Definition at line 2917 of file pbx_dundi.c.

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

2918 {
2919 #define FORMAT2 "%-12.12s %-12.12s %-10.10s\n"
2920 #define FORMAT "%-12.12s %-12.12s %02d:%02d:%02d\n"
2921  struct dundi_precache_queue *qe;
2922  int h,m,s;
2923  time_t now;
2924  switch (cmd) {
2925  case CLI_INIT:
2926  e->command = "dundi show precache";
2927  e->usage =
2928  "Usage: dundi show precache\n"
2929  " Lists all known DUNDi scheduled precache updates.\n";
2930  return NULL;
2931  case CLI_GENERATE:
2932  return NULL;
2933  }
2934  if (a->argc != 3) {
2935  return CLI_SHOWUSAGE;
2936  }
2937  time(&now);
2938  ast_cli(a->fd, FORMAT2, "Number", "Context", "Expiration");
2939  AST_LIST_LOCK(&pcq);
2940  AST_LIST_TRAVERSE(&pcq, qe, list) {
2941  s = qe->expiration - now;
2942  h = s / 3600;
2943  s = s % 3600;
2944  m = s / 60;
2945  s = s % 60;
2946  ast_cli(a->fd, FORMAT, qe->number, qe->context, h,m,s);
2947  }
2948  AST_LIST_UNLOCK(&pcq);
2949 
2950  return CLI_SUCCESS;
2951 #undef FORMAT
2952 #undef FORMAT2
2953 }
Definition: pbx_dundi.c:342
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
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
#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
#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
char * command
Definition: cli.h:186
struct dundi_precache_queue::@437 list
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
#define FORMAT
#define FORMAT2

◆ dundi_show_requests()

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

Definition at line 2850 of file pbx_dundi.c.

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

2851 {
2852 #define FORMAT2 "%-15s %-15s %-15s %-3.3s %-3.3s\n"
2853 #define FORMAT "%-15s %-15s %-15s %-3.3d %-3.3d\n"
2854  struct dundi_request *req;
2855  char eidstr[20];
2856  switch (cmd) {
2857  case CLI_INIT:
2858  e->command = "dundi show requests";
2859  e->usage =
2860  "Usage: dundi show requests\n"
2861  " Lists all known pending DUNDi requests.\n";
2862  return NULL;
2863  case CLI_GENERATE:
2864  return NULL;
2865  }
2866  if (a->argc != 3) {
2867  return CLI_SHOWUSAGE;
2868  }
2869  AST_LIST_LOCK(&peers);
2870  ast_cli(a->fd, FORMAT2, "Number", "Context", "Root", "Max", "Rsp");
2871  AST_LIST_TRAVERSE(&requests, req, list) {
2872  ast_cli(a->fd, FORMAT, req->number, req->dcontext,
2873  dundi_eid_zero(&req->root_eid) ? "<unspecified>" : ast_eid_to_str(eidstr, sizeof(eidstr), &req->root_eid), req->maxcount, req->respcount);
2874  }
2876  return CLI_SUCCESS;
2877 #undef FORMAT
2878 #undef FORMAT2
2879 }
#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
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
#define NULL
Definition: resample.c:96
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:274
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
const int fd
Definition: cli.h:159
char number[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:275
#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
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
dundi_eid root_eid
Definition: pbx_dundi.c:277
#define FORMAT
int dundi_eid_zero(dundi_eid *eid)
Definition: dundi-parser.c:82
#define FORMAT2
struct dundi_request::@441 list

◆ dundi_show_trans()

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

Definition at line 2796 of file pbx_dundi.c.

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

2797 {
2798 #define FORMAT2 "%-47s %-5.5s %-5.5s %-3.3s %-3.3s %-3.3s\n"
2799 #define FORMAT "%-41s:%5d %-5.5d %-5.5d %-3.3d %-3.3d %-3.3d\n"
2800  struct dundi_transaction *trans;
2801  switch (cmd) {
2802  case CLI_INIT:
2803  e->command = "dundi show trans";
2804  e->usage =
2805  "Usage: dundi show trans\n"
2806  " Lists all known DUNDi transactions.\n";
2807  return NULL;
2808  case CLI_GENERATE:
2809  return NULL;
2810  }
2811  if (a->argc != 3) {
2812  return CLI_SHOWUSAGE;
2813  }
2814  AST_LIST_LOCK(&peers);
2815  ast_cli(a->fd, FORMAT2, "Remote", "Src", "Dst", "Tx", "Rx", "Ack");
2816  AST_LIST_TRAVERSE(&alltrans, trans, all) {
2818  ast_sockaddr_port(&trans->addr), trans->strans, trans->dtrans,
2819  trans->oseqno, trans->iseqno, trans->aseqno);
2820  }
2822  return CLI_SUCCESS;
2823 #undef FORMAT
2824 #undef FORMAT2
2825 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
unsigned char aseqno
Definition: pbx_dundi.c:265
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
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
struct dundi_transaction::@439 all
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
Definition: netsock2.h:521
const int fd
Definition: cli.h:159
unsigned short strans
Definition: pbx_dundi.c:260
#define CLI_SHOWUSAGE
Definition: cli.h:45
unsigned char oseqno
Definition: pbx_dundi.c:264
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
unsigned short dtrans
Definition: pbx_dundi.c:261
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
#define FORMAT
#define FORMAT2
unsigned char iseqno
Definition: pbx_dundi.c:262
struct ast_sockaddr addr
Definition: pbx_dundi.c:246
static char * ast_sockaddr_stringify_host(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only, suitable for a URL (with brack...
Definition: netsock2.h:331

◆ dundi_sockaddr_port()

static uint16_t dundi_sockaddr_port ( const struct ast_sockaddr addr)
static

Definition at line 2609 of file pbx_dundi.c.

References ast_sockaddr_isnull(), and ast_sockaddr_port.

Referenced by dundi_show_peer(), and dundi_show_peers().

2610 {
2611  /*
2612  * Test to avoid a debug message complaining about addr
2613  * not being an IPv4 or IPv6 address.
2614  */
2615  if (ast_sockaddr_isnull(addr)) {
2616  return 0;
2617  }
2618  return ast_sockaddr_port(addr);
2619 }
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_sockaddr_port(addr)
Get the port number of a socket address.
Definition: netsock2.h:521

◆ dundi_sockaddr_stringify_host()

static char* dundi_sockaddr_stringify_host ( const struct ast_sockaddr addr)
static

Definition at line 2601 of file pbx_dundi.c.

References ast_sockaddr_isnull(), and ast_sockaddr_stringify_host().

Referenced by dundi_show_peers().

2602 {
2603  if (ast_sockaddr_isnull(addr)) {
2604  return "(Unspecified)";
2605  }
2606  return ast_sockaddr_stringify_host(addr);
2607 }
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
static char * ast_sockaddr_stringify_host(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only, suitable for a URL (with brack...
Definition: netsock2.h:331

◆ dundi_store_history()

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

Definition at line 2330 of file pbx_dundi.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, NULL, and ast_cli_entry::usage.

2331 {
2332  switch (cmd) {
2333  case CLI_INIT:
2334  e->command = "dundi store history {on|off}";
2335  e->usage =
2336  "Usage: dundi store history {on|off}\n"
2337  " Enables/Disables storing of DUNDi requests and times for debugging\n"
2338  "purposes\n";
2339  return NULL;
2340  case CLI_GENERATE:
2341  return NULL;
2342  }
2343 
2344  if (a->argc != e->args) {
2345  return CLI_SHOWUSAGE;
2346  }
2347  if (!strncasecmp(a->argv[e->args -1], "on", 2)) {
2348  global_storehistory = 1;
2349  ast_cli(a->fd, "DUNDi History Storage Enabled\n");
2350  } else {
2351  global_storehistory = 0;
2352  ast_cli(a->fd, "DUNDi History Storage Disabled\n");
2353  }
2354  return CLI_SUCCESS;
2355 }
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
int args
This gets set in ast_cli_register()
Definition: cli.h:185
const int fd
Definition: cli.h:159
static int global_storehistory
Definition: pbx_dundi.c:200
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

◆ dundi_xmit()

static int dundi_xmit ( struct dundi_packet pack)
static

Definition at line 3169 of file pbx_dundi.c.

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

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

3170 {
3171  int res;
3172  if (dundidebug)
3173  dundi_showframe(pack->h, 0, &pack->parent->addr, pack->datalen - sizeof(struct dundi_hdr));
3174 
3175  if (netsocket2 < 0) {
3176  res = ast_sendto(netsocket, pack->data, pack->datalen, 0, &pack->parent->addr);
3177  } else {
3178  if (ast_sockaddr_is_ipv4(&pack->parent->addr)) {
3179  res = ast_sendto(netsocket, pack->data, pack->datalen, 0, &pack->parent->addr);
3180  } else {
3181  res = ast_sendto(netsocket2, pack->data, pack->datalen, 0, &pack->parent->addr);
3182  }
3183  }
3184 
3185  if (res < 0) {
3186  ast_log(LOG_WARNING, "Failed to transmit to '%s': %s\n",
3187  ast_sockaddr_stringify(&pack->parent->addr), strerror(errno));
3188  }
3189  if (res > 0)
3190  res = 0;
3191  return res;
3192 }
ssize_t ast_sendto(int sockfd, const void *buf, size_t len, int flags, const struct ast_sockaddr *dest_addr)
Wrapper around sendto(2) that uses ast_sockaddr.
Definition: netsock2.c:614
#define LOG_WARNING
Definition: logger.h:274
unsigned char data[0]
Definition: pbx_dundi.c:228
static int netsocket
Definition: pbx_dundi.c:186
#define ast_log
Definition: astobj2.c:42
static int dundidebug
Definition: pbx_dundi.c:192
int errno
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
void dundi_showframe(struct dundi_hdr *fhi, int rx, struct ast_sockaddr *sin, int datalen)
Definition: dundi-parser.c:432
int ast_sockaddr_is_ipv4(const struct ast_sockaddr *addr)
Determine if the address is an IPv4 address.
Definition: netsock2.c:497
struct dundi_transaction * parent
Definition: pbx_dundi.c:225
struct ast_sockaddr addr
Definition: pbx_dundi.c:246
struct dundi_hdr * h
Definition: pbx_dundi.c:223
static int netsocket2
Definition: pbx_dundi.c:187

◆ dundifunc_read()

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

Definition at line 4137 of file pbx_dundi.c.

References args, AST_APP_ARG, ast_app_parse_options(), AST_DECLARE_APP_ARGS, ast_log, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero, ast_test_flag, DUNDI_FLAG_EXISTS, dundi_lookup(), dundi_query_opts, LOG_WARNING, NULL, OPT_BYPASS_CACHE, options, parse(), and sort_results().

4138 {
4139  int results;
4140  int x;
4141  struct dundi_result dr[MAX_RESULTS];
4146  );
4147  char *parse;
4148  struct ast_flags opts = { 0, };
4149 
4150  buf[0] = '\0';
4151 
4152  if (ast_strlen_zero(num)) {
4153  ast_log(LOG_WARNING, "DUNDILOOKUP requires an argument (number)\n");
4154  return -1;
4155  }
4156 
4157  parse = ast_strdupa(num);
4158 
4159  AST_STANDARD_APP_ARGS(args, parse);
4160 
4161  if (!ast_strlen_zero(args.options)) {
4162  ast_app_parse_options(dundi_query_opts, &opts, NULL, args.options);
4163  }
4164  if (ast_strlen_zero(args.context)) {
4165  args.context = "e164";
4166  }
4167 
4168  results = dundi_lookup(dr, MAX_RESULTS, NULL, args.context, args.number, ast_test_flag(&opts, OPT_BYPASS_CACHE));
4169  if (results > 0) {
4170  sort_results(dr, results);
4171  for (x = 0; x < results; x++) {
4172  if (ast_test_flag(dr + x, DUNDI_FLAG_EXISTS)) {
4173  snprintf(buf, len, "%s/%s", dr[x].tech, dr[x].dest);
4174  break;
4175  }
4176  }
4177  }
4178 
4179  return 0;
4180 }
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
#define ast_test_flag(p, flag)
Definition: utils.h:63
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define LOG_WARNING
Definition: logger.h:274
#define MAX_RESULTS
Definition: pbx_dundi.c:153
const char * args
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
Number structure.
Definition: app_followme.c:154
#define ast_log
Definition: astobj2.c:42
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:2906
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
Structure used to handle boolean flags.
Definition: utils.h:199
static struct test_options options
static const struct ast_app_option dundi_query_opts[128]
Definition: pbx_dundi.c:4135
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

◆ encrypt_memcpy()

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

Definition at line 1373 of file pbx_dundi.c.

References ast_aes_encrypt().

Referenced by dundi_encrypt().

1374 {
1375  unsigned char curblock[16];
1376  int x;
1377  memcpy(curblock, iv, sizeof(curblock));
1378  while(len > 0) {
1379  for (x=0;x<16;x++)
1380  curblock[x] ^= src[x];
1381  ast_aes_encrypt(curblock, dst, ecx);
1382  memcpy(curblock, dst, sizeof(curblock));
1383  dst += 16;
1384  src += 16;
1385  len -= 16;
1386  }
1387  return 0;
1388 }
void AST_OPTIONAL_API_NAME() ast_aes_encrypt(const unsigned char *in, unsigned char *out, const ast_aes_encrypt_key *ctx)
Definition: res_crypto.c:476
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)

◆ find_peer()

static struct dundi_peer* find_peer ( dundi_eid eid)
static

Definition at line 515 of file pbx_dundi.c.

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

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

516 {
517  struct dundi_peer *cur = NULL;
518 
519  if (!eid)
520  eid = &empty_eid;
521 
522  AST_LIST_TRAVERSE(&peers, cur, list) {
523  if (!ast_eid_cmp(&cur->eid,eid))
524  break;
525  }
526 
527  if (!cur && any_peer)
528  cur = any_peer;
529 
530  return cur;
531 }
struct dundi_peer::@443 list
#define NULL
Definition: resample.c:96
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
Definition: main/utils.c:2842
static struct dundi_peer * any_peer
Wildcard peer.
Definition: pbx_dundi.c:352
static dundi_eid empty_eid
Definition: pbx_dundi.c:212
#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

◆ find_transaction()

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

Definition at line 412 of file pbx_dundi.c.

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

Referenced by handle_frame().

413 {
414  struct dundi_transaction *trans;
415 
416  /* Look for an exact match first */
417  AST_LIST_TRAVERSE(&alltrans, trans, all) {
418  if (!ast_sockaddr_cmp(&trans->addr, sin) &&
419  ((trans->strans == (ntohs(hdr->dtrans) & 32767)) /* Matches our destination */ ||
420  ((trans->dtrans == (ntohs(hdr->strans) & 32767)) && (!hdr->dtrans))) /* We match their destination */) {
421  if (hdr->strans) {
422  trans->dtrans = ntohs(hdr->strans) & 32767;
423  }
424  return trans;
425  }
426  }
427 
428  switch(hdr->cmdresp & 0x7f) {
433  case DUNDI_COMMAND_NULL:
435  if (!hdr->strans)
436  break;
437  /* Create new transaction */
438  if (!(trans = create_transaction(NULL)))
439  break;
440  ast_sockaddr_copy(&trans->addr, sin);
441  trans->dtrans = ntohs(hdr->strans) & 32767;
442  default:
443  break;
444  }
445 
446  return trans;
447 }
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 DUNDI_COMMAND_ENCRYPT
Definition: dundi.h:172
unsigned char cmdresp
Definition: dundi.h:39
#define NULL
Definition: resample.c:96
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares two ast_sockaddr structures.
Definition: netsock2.c:388
struct dundi_transaction::@439 all
static struct dundi_transaction * create_transaction(struct dundi_peer *p)
Definition: pbx_dundi.c:3137
unsigned short strans
Definition: pbx_dundi.c:260
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
unsigned short dtrans
Definition: pbx_dundi.c:261
unsigned short strans
Definition: dundi.h:35
#define DUNDI_COMMAND_PRECACHERQ
Definition: dundi.h:164
#define DUNDI_COMMAND_REGREQ
Definition: dundi.h:169
#define DUNDI_COMMAND_EIDQUERY
Definition: dundi.h:162
#define DUNDI_COMMAND_DPDISCOVER
Definition: dundi.h:160
unsigned short dtrans
Definition: dundi.h:36
struct ast_sockaddr addr
Definition: pbx_dundi.c:246
#define DUNDI_COMMAND_NULL
Definition: dundi.h:168

◆ get_ipaddress()

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

Definition at line 4901 of file pbx_dundi.c.

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

Referenced by set_config(), and set_host_ipaddr().

4902 {
4903  struct ast_sockaddr *addrs;
4904 
4905  if (!ast_sockaddr_resolve(&addrs, str, 0, family)) {
4906  return -1;
4907  }
4908 
4909  ast_copy_string(ip, ast_sockaddr_stringify_host(&addrs[0]), size);
4910  ast_free(addrs);
4911 
4912  return 0;
4913 }
const char * str
Definition: app_jack.c:147
Socket address structure.
Definition: netsock2.h:97
#define ast_free(a)
Definition: astmm.h:182
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static char * ast_sockaddr_stringify_host(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only, suitable for a URL (with brack...
Definition: netsock2.h:331
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

◆ get_mapping_weight()

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

Definition at line 559 of file pbx_dundi.c.

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

Referenced by dundi_lookup_local(), and dundi_show_mappings().

560 {
561  char buf[32];
562 
563  buf[0] = 0;
564  if (map->weightstr) {
565  if (headp) {
566  pbx_substitute_variables_varshead(headp, map->weightstr, buf, sizeof(buf) - 1);
567  } else {
568  pbx_substitute_variables_helper(NULL, map->weightstr, buf, sizeof(buf) - 1);
569  }
570 
571  if (sscanf(buf, "%30d", &map->_weight) != 1)
572  map->_weight = MAX_WEIGHT;
573  }
574 
575  return map->_weight;
576 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define NULL
Definition: resample.c:96
char * weightstr
Definition: pbx_dundi.c:295
void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
Definition: ael_main.c:211
#define MAX_WEIGHT
Definition: pbx_dundi.c:157
void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count)

◆ get_trans_id()

static int get_trans_id ( void  )
static

Definition at line 480 of file pbx_dundi.c.

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

Referenced by create_transaction(), and reset_transaction().

481 {
482  struct dundi_transaction *t;
483  int stid = (ast_random() % 32766) + 1;
484  int tid = stid;
485 
486  do {
488  if (t->strans == tid)
489  break;
490  }
491  if (!t)
492  return tid;
493  tid = (tid % 32766) + 1;
494  } while (tid != stid);
495 
496  return 0;
497 }
struct dundi_transaction::@439 all
long int ast_random(void)
Definition: main/utils.c:2064
unsigned short strans
Definition: pbx_dundi.c:260
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490

◆ handle_command_response()

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

Definition at line 1586 of file pbx_dundi.c.

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

Referenced by handle_frame().

1587 {
1588  /* Handle canonical command / response */
1589  int final = hdr->cmdresp & 0x80;
1590  int cmd = hdr->cmdresp & 0x7f;
1591  int x,y,z;
1592  int resp;
1593  int res;
1594  int authpass=0;
1595  unsigned char *bufcpy;
1596 #ifdef LOW_MEMORY
1597  struct dundi_ie_data *ied = ast_calloc(1, sizeof(*ied));
1598 #else
1599  struct dundi_ie_data _ied = {
1600  .pos = 0,
1601  };
1602  struct dundi_ie_data *ied = &_ied;
1603 #endif
1604  struct dundi_ies ies = {
1605  .eidcount = 0,
1606  };
1607  struct dundi_peer *peer = NULL;
1608  char eid_str[20];
1609  char eid_str2[20];
1610  int retval = -1;
1611 
1612  if (!ied) {
1613  return -1;
1614  }
1615 
1616  if (datalen) {
1617  bufcpy = ast_alloca(datalen);
1618  /* Make a copy for parsing */
1619  memcpy(bufcpy, hdr->ies, datalen);
1620  ast_debug(1, "Got canonical message %d (%d), %d bytes data%s\n", cmd, hdr->oseqno, datalen, final ? " (Final)" : "");
1621  if (dundi_parse_ies(&ies, bufcpy, datalen) < 0) {
1622  ast_log(LOG_WARNING, "Failed to parse DUNDI information elements!\n");
1623  goto return_cleanup;
1624  }
1625  }
1626  switch(cmd) {
1630  if (cmd == DUNDI_COMMAND_EIDQUERY)
1632  else if (cmd == DUNDI_COMMAND_PRECACHERQ)
1633  resp = DUNDI_COMMAND_PRECACHERP;
1634  else
1635  resp = DUNDI_COMMAND_DPRESPONSE;
1636  /* A dialplan or entity discover -- qualify by highest level entity */
1637  peer = find_peer(ies.eids[0]);
1638  if (!peer) {
1640  dundi_send(trans, resp, 0, 1, ied);
1641  } else {
1642  int hasauth = 0;
1643  trans->us_eid = peer->us_eid;
1644  if (strlen(peer->inkey)) {
1645  hasauth = encrypted;
1646  } else
1647  hasauth = 1;
1648  if (hasauth) {
1649  /* Okay we're authentiated and all, now we check if they're authorized */
1650  if (!ies.called_context)
1651  ies.called_context = "e164";
1652  if (cmd == DUNDI_COMMAND_EIDQUERY) {
1653  res = dundi_answer_entity(trans, &ies, ies.called_context);
1654  } else {
1655  if (ast_strlen_zero(ies.called_number)) {
1656  /* They're not permitted to access that context */
1657  dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Invalid or missing number/entity");
1658  dundi_send(trans, resp, 0, 1, ied);
1659  } else if ((cmd == DUNDI_COMMAND_DPDISCOVER) &&
1660  (peer->model & DUNDI_MODEL_INBOUND) &&
1661  has_permission(&peer->permit, ies.called_context)) {
1662  res = dundi_answer_query(trans, &ies, ies.called_context);
1663  if (res < 0) {
1664  /* There is no such dundi context */
1665  dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Unsupported DUNDI Context");
1666  dundi_send(trans, resp, 0, 1, ied);
1667  }
1668  } else if ((cmd = DUNDI_COMMAND_PRECACHERQ) &&
1669  (peer->pcmodel & DUNDI_MODEL_INBOUND) &&
1670  has_permission(&peer->include, ies.called_context)) {
1671  res = dundi_prop_precache(trans, &ies, ies.called_context);
1672  if (res < 0) {
1673  /* There is no such dundi context */
1674  dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Unsupported DUNDI Context");
1675  dundi_send(trans, resp, 0, 1, ied);
1676  }
1677  } else {
1678  /* They're not permitted to access that context */
1679  dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Permission to context denied");
1680  dundi_send(trans, resp, 0, 1, ied);
1681  }
1682  }
1683  } else {
1684  /* They're not permitted to access that context */
1685  dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Unencrypted responses not permitted");
1686  dundi_send(trans, resp, 0, 1, ied);
1687  }
1688  }
1689  break;
1690  case DUNDI_COMMAND_REGREQ:
1691  /* A register request -- should only have one entity */
1692  peer = find_peer(ies.eids[0]);
1693 
1694  /* if the peer is not found and we have a valid 'any_peer' setting */
1695  if (any_peer && peer == any_peer) {
1696  /* copy any_peer into a new peer object */
1697  peer = ast_calloc(1, sizeof(*peer));
1698  if (peer) {
1699  deep_copy_peer(peer, any_peer);
1700 
1701  /* set EID to remote EID */
1702  peer->eid = *ies.eids[0];
1703 
1704  AST_LIST_LOCK(&peers);
1705  AST_LIST_INSERT_HEAD(&peers, peer, list);
1707  }
1708  }
1709 
1710  if (!peer || !peer->dynamic) {
1712  dundi_send(trans, DUNDI_COMMAND_REGRESPONSE, 0, 1, ied);
1713  } else {
1714  int hasauth = 0;
1715  trans->us_eid = peer->us_eid;
1716  if (!ast_strlen_zero(peer->inkey)) {
1717  hasauth = encrypted;
1718  } else
1719  hasauth = 1;
1720  if (hasauth) {
1721  int expire = default_expiration;
1722  char data[256];
1723  int needqual = 0;
1725  peer->registerexpire = ast_sched_add(sched, (expire + 10) * 1000, do_register_expire, peer);
1726  snprintf(data, sizeof(data), "%s:%d", ast_sockaddr_stringify(&trans->addr), expire);
1727  ast_db_put("dundi/dpeers", dundi_eid_to_str_short(eid_str, sizeof(eid_str), &peer->eid), data);
1728  if (ast_sockaddr_cmp(&peer->addr, &trans->addr)) {
1729  ast_verb(3, "Registered DUNDi peer '%s' at '%s'\n",
1730  ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid),
1731  ast_sockaddr_stringify(&trans->addr));
1732  needqual = 1;
1733  }
1734 
1735  ast_sockaddr_copy(&peer->addr, &trans->addr);
1737  dundi_send(trans, DUNDI_COMMAND_REGRESPONSE, 0, 1, ied);
1738  if (needqual)
1739  qualify_peer(peer, 1);
1740  }
1741  }
1742  break;
1744  /* A dialplan response, lets see what we got... */
1745  if (ies.cause < 1) {
1746  /* Success of some sort */
1747  ast_debug(1, "Looks like success of some sort (%d), %d answers\n", ies.cause, ies.anscount);
1748  if (ast_test_flag(trans, FLAG_ENCRYPT)) {
1749  authpass = encrypted;
1750  } else
1751  authpass = 1;
1752  if (authpass) {
1753  /* Pass back up answers */
1754  if (trans->parent && trans->parent->dr) {
1755  y = trans->parent->respcount;
1756  for (x=0;x<ies.anscount;x++) {
1757  if (trans->parent->respcount < trans->parent->maxcount) {
1758  /* Make sure it's not already there */
1759  for (z=0;z<trans->parent->respcount;z++) {
1760  if ((trans->parent->dr[z].techint == ies.answers[x]->protocol) &&
1761  !strcmp(trans->parent->dr[z].dest, (char *)ies.answers[x]->data))
1762  break;
1763  }
1764  if (z == trans->parent->respcount) {
1765  /* Copy into parent responses */
1766  trans->parent->dr[trans->parent->respcount].flags = ntohs(ies.answers[x]->flags);
1767  trans->parent->dr[trans->parent->respcount].techint = ies.answers[x]->protocol;
1768  trans->parent->dr[trans->parent->respcount].weight = ntohs(ies.answers[x]->weight);
1769  trans->parent->dr[trans->parent->respcount].eid = ies.answers[x]->eid;
1770  if (ies.expiration > 0)
1771  trans->parent->dr[trans->parent->respcount].expiration = ies.expiration;
1772  else
1773  trans->parent->dr[trans->parent->respcount].expiration = dundi_cache_time;
1774  ast_eid_to_str(trans->parent->dr[trans->parent->respcount].eid_str,
1775  sizeof(trans->parent->dr[trans->parent->respcount].eid_str),
1776  &ies.answers[x]->eid);
1777  ast_copy_string(trans->parent->dr[trans->parent->respcount].dest, (char *)ies.answers[x]->data,
1778  sizeof(trans->parent->dr[trans->parent->respcount].dest));
1779  ast_copy_string(trans->parent->dr[trans->parent->respcount].tech, tech2str(ies.answers[x]->protocol),
1780  sizeof(trans->parent->dr[trans->parent->respcount].tech));
1781  trans->parent->respcount++;
1783  } else if (trans->parent->dr[z].weight > ntohs(ies.answers[x]->weight)) {
1784  /* Update weight if appropriate */
1785  trans->parent->dr[z].weight = ntohs(ies.answers[x]->weight);
1786  }
1787  } else
1788  ast_log(LOG_NOTICE, "Dropping excessive answers to request for %s@%s\n",
1789  trans->parent->number, trans->parent->dcontext);
1790  }
1791  /* Save all the results (if any) we had. Even if no results, still cache lookup. Let
1792  the cache know if this request was unaffected by our entity list. */
1793  cache_save(&trans->them_eid, trans->parent, y,
1794  ies.hint ? ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_UNAFFECTED)) : 0, ies.expiration, 0);
1795  if (ies.hint) {
1796  cache_save_hint(&trans->them_eid, trans->parent, ies.hint, ies.expiration);
1799  if (ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_DONT_ASK))) {
1800  if (strlen((char *)ies.hint->data) > strlen(trans->parent->hmd->exten)) {
1801  ast_copy_string(trans->parent->hmd->exten, (char *)ies.hint->data,
1802  sizeof(trans->parent->hmd->exten));
1803  }
1804  } else {
1806  }
1807  }
1808  if (ies.expiration > 0) {
1809  if (trans->parent->expiration > ies.expiration) {
1810  trans->parent->expiration = ies.expiration;
1811  }
1812  }
1813  }
1814  /* Close connection if not final */
1815  if (!final)
1816  dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
1817  }
1818 
1819  } else {
1820  /* Auth failure, check for data */
1821  if (!final) {
1822  /* Cancel if they didn't already */
1823  dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
1824  }
1825  }
1826  break;
1828  /* A dialplan response, lets see what we got... */
1829  if (ies.cause < 1) {
1830  /* Success of some sort */
1831  ast_debug(1, "Looks like success of some sort (%d)\n", ies.cause);
1832  if (ast_test_flag(trans, FLAG_ENCRYPT)) {
1833  authpass = encrypted;
1834  } else
1835  authpass = 1;
1836  if (authpass) {
1837  /* Pass back up answers */
1838  if (trans->parent && trans->parent->dei && ies.q_org) {
1839  if (!trans->parent->respcount) {
1840  trans->parent->respcount++;
1841  if (ies.q_dept)
1842  ast_copy_string(trans->parent->dei->orgunit, ies.q_dept, sizeof(trans->parent->dei->orgunit));
1843  if (ies.q_org)
1844  ast_copy_string(trans->parent->dei->org, ies.q_org, sizeof(trans->parent->dei->org));
1845  if (ies.q_locality)
1846  ast_copy_string(trans->parent->dei->locality, ies.q_locality, sizeof(trans->parent->dei->locality));
1847  if (ies.q_stateprov)
1848  ast_copy_string(trans->parent->dei->stateprov, ies.q_stateprov, sizeof(trans->parent->dei->stateprov));
1849  if (ies.q_country)
1850  ast_copy_string(trans->parent->dei->country, ies.q_country, sizeof(trans->parent->dei->country));
1851  if (ies.q_email)
1852  ast_copy_string(trans->parent->dei->email, ies.q_email, sizeof(trans->parent->dei->email));
1853  if (ies.q_phone)
1854  ast_copy_string(trans->parent->dei->phone, ies.q_phone, sizeof(trans->parent->dei->phone));
1855  if (ies.q_ipaddr)
1856  ast_copy_string(trans->parent->dei->ipaddr, ies.q_ipaddr, sizeof(trans->parent->dei->ipaddr));
1857  if (!ast_eid_cmp(&trans->them_eid, &trans->parent->query_eid)) {
1858  /* If it's them, update our address */
1859  ast_copy_string(trans->parent->dei->ipaddr, ast_sockaddr_stringify_addr(&trans->addr), sizeof(trans->parent->dei->ipaddr));
1860  }
1861  }
1862  if (ies.hint) {
1865  }
1866  }
1867  /* Close connection if not final */
1868  if (!final)
1869  dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
1870  }
1871 
1872  } else {
1873  /* Auth failure, check for data */
1874  if (!final) {
1875  /* Cancel if they didn't already */
1876  dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
1877  }
1878  }
1879  break;
1881  /* A dialplan response, lets see what we got... */
1882  if (ies.cause < 1) {
1883  int hasauth;
1884  /* Success of some sort */
1885  if (ast_test_flag(trans, FLAG_ENCRYPT)) {
1886  hasauth = encrypted;
1887  } else
1888  hasauth = 1;
1889 
1890  if (!hasauth) {
1891  ast_log(LOG_NOTICE, "Reponse to register not authorized!\n");
1892  if (!final) {
1893  dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Improper signature in answer");
1894  dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, ied);
1895  }
1896  } else {
1897  ast_debug(1, "Yay, we've registered as '%s' to '%s'\n", ast_eid_to_str(eid_str, sizeof(eid_str), &trans->us_eid),
1898  ast_eid_to_str(eid_str2, sizeof(eid_str2), &trans->them_eid));
1899  /* Close connection if not final */
1900  if (!final)
1901  dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
1902  }
1903  } else {
1904  /* Auth failure, cancel if they didn't for some reason */
1905  if (!final) {
1906  dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
1907  }
1908  }
1909  break;
1910  case DUNDI_COMMAND_INVALID:
1911  case DUNDI_COMMAND_NULL:
1913  /* Do nothing special */
1914  if (!final)
1915  dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
1916  break;
1917  case DUNDI_COMMAND_ENCREJ:
1918  if ((ast_test_flag(trans, FLAG_SENDFULLKEY)) || AST_LIST_EMPTY(&trans->lasttrans) || !(peer = find_peer(&trans->them_eid))) {
1919  /* No really, it's over at this point */
1920  if (!final)
1921  dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
1922  } else {
1923  /* Send with full key */
1925  if (final) {
1926  /* Ooops, we got a final message, start by sending ACK... */
1927  dundi_ack(trans, hdr->cmdresp & 0x80);
1928  trans->aseqno = trans->iseqno;
1929  /* Now, we gotta create a new transaction */
1930  if (!reset_transaction(trans)) {
1931  /* Make sure handle_frame doesn't destroy us */
1932  hdr->cmdresp &= 0x7f;
1933  /* Parse the message we transmitted */
1934  memset(&ies, 0, sizeof(ies));
1935  dundi_parse_ies(&ies, (AST_LIST_FIRST(&trans->lasttrans))->h->ies, (AST_LIST_FIRST(&trans->lasttrans))->datalen - sizeof(struct dundi_hdr));
1936  /* Reconstruct outgoing encrypted packet */
1937  memset(ied, 0, sizeof(*ied));
1938  dundi_ie_append_eid(ied, DUNDI_IE_EID, &trans->us_eid);
1940  dundi_ie_append_raw(ied, DUNDI_IE_SIGNATURE, peer->txenckey + 128, 128);
1941  if (ies.encblock)
1943  dundi_send(trans, DUNDI_COMMAND_ENCRYPT, 0, (AST_LIST_FIRST(&trans->lasttrans))->h->cmdresp & 0x80, ied);
1944  peer->sentfullkey = 1;
1945  }
1946  }
1947  }
1948  break;
1949  case DUNDI_COMMAND_ENCRYPT:
1950  if (!encrypted) {
1951  /* No nested encryption! */
1952  if ((trans->iseqno == 1) && !trans->oseqno) {
1953  if (!ies.eids[0] || !(peer = find_peer(ies.eids[0])) ||
1954  ((!ies.encsharedkey || !ies.encsig) && !ies.keycrc32) ||
1955  (check_key(peer, ies.encsharedkey, ies.encsig, ies.keycrc32) < 1)) {
1956  if (!final) {
1957  dundi_send(trans, DUNDI_COMMAND_ENCREJ, 0, 1, NULL);
1958  }
1959  break;
1960  }
1961  apply_peer(trans, peer);
1962  /* Key passed, use new contexts for this session */
1963  trans->ecx = peer->them_ecx;
1964  trans->dcx = peer->them_dcx;
1965  }
1966  if (ast_test_flag(trans, FLAG_ENCRYPT) && ies.encblock && ies.enclen) {
1967  struct dundi_hdr *dhdr;
1968  unsigned char decoded[MAX_PACKET_SIZE];
1969  int ddatalen;
1970  ddatalen = sizeof(decoded);
1971  dhdr = dundi_decrypt(trans, decoded, &ddatalen, hdr, ies.encblock, ies.enclen);
1972  if (dhdr) {
1973  /* Handle decrypted response */
1974  if (dundidebug)
1975  dundi_showframe(dhdr, 3, &trans->addr, ddatalen - sizeof(struct dundi_hdr));
1976  handle_command_response(trans, dhdr, ddatalen - sizeof(struct dundi_hdr), 1);
1977  /* Carry back final flag */
1978  hdr->cmdresp |= dhdr->cmdresp & 0x80;
1979  break;
1980  } else {
1981  ast_debug(1, "Ouch, decrypt failed :(\n");
1982  }
1983  }
1984  }
1985  if (!final) {
1986  /* Turn off encryption */
1987  ast_clear_flag(trans, FLAG_ENCRYPT);
1988  dundi_send(trans, DUNDI_COMMAND_ENCREJ, 0, 1, NULL);
1989  }
1990  break;
1991  default:
1992  /* Send unknown command if we don't know it, with final flag IFF it's the
1993  first command in the dialog and only if we haven't received final notification */
1994  if (!final) {
1996  dundi_send(trans, DUNDI_COMMAND_UNKNOWN, 0, !hdr->oseqno, ied);
1997  }
1998  }
1999 
2000  retval = 0;
2001 
2002 return_cleanup:
2003 #ifdef LOW_MEMORY
2004  ast_free(ied);
2005 #endif
2006  return retval;
2007 }
static char * ast_sockaddr_stringify_addr(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only.
Definition: netsock2.h:290
struct dundi_peer::@443 list
static void apply_peer(struct dundi_transaction *trans, struct dundi_peer *p)
Definition: pbx_dundi.c:1295
char locality[80]
Definition: dundi.h:239
char phone[80]
Definition: dundi.h:243
#define DUNDI_IE_EXPIRATION
Definition: dundi.h:189
char org[80]
Definition: dundi.h:240
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
static int dundi_answer_query(struct dundi_transaction *trans, struct dundi_ies *ies, char *ccontext)
Definition: pbx_dundi.c:1087
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
unsigned char aseqno
Definition: pbx_dundi.c:265
static int reset_transaction(struct dundi_transaction *trans)
Definition: pbx_dundi.c:499
char country[80]
Definition: dundi.h:237
ast_aes_encrypt_key ecx
Definition: pbx_dundi.c:252
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
int weight
Definition: dundi.h:227
static int dundi_cache_time
Definition: pbx_dundi.c:196
#define DUNDI_COMMAND_ENCREJ
Definition: dundi.h:173
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 do_register_expire(const void *data)
Definition: pbx_dundi.c:1321
#define ast_test_flag(p, flag)
Definition: utils.h:63
char orgunit[80]
Definition: dundi.h:241
struct dundi_entity_info * dei
Definition: pbx_dundi.c:279
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
unsigned char encdata[0]
Definition: dundi.h:99
#define ast_clear_flag_nonstd(p, flag)
Definition: utils.h:180
#define ast_set_flag(p, flag)
Definition: utils.h:70
struct dundi_answer * answers[DUNDI_MAX_ANSWERS+1]
Definition: dundi-parser.h:28
static char * tech2str(int tech)
Definition: pbx_dundi.c:380
char * q_org
Definition: dundi-parser.h:38
#define LOG_WARNING
Definition: logger.h:274
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
char ipaddr[80]
Definition: dundi.h:244
#define DUNDI_IE_SHAREDKEY
Definition: dundi.h:194
char * q_locality
Definition: dundi-parser.h:39
char * dundi_eid_to_str_short(char *s, int maxlen, dundi_eid *eid)
Definition: dundi-parser.c:54
#define DUNDI_IE_CAUSE
Definition: dundi.h:191
Definition: sched.c:76
struct dundi_result * dr
Definition: pbx_dundi.c:278
int registerexpire
Definition: pbx_dundi.c:325
static void deep_copy_peer(struct dundi_peer *peer_dst, const struct dundi_peer *peer_src)
Definition: pbx_dundi.c:1545
char dest[256]
Definition: dundi.h:233
#define DUNDI_COMMAND_ENCRYPT
Definition: dundi.h:172
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 AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
char * called_number
Definition: dundi-parser.h:27
static void qualify_peer(struct dundi_peer *peer, int schedonly)
Definition: pbx_dundi.c:4565
static int dundi_prop_precache(struct dundi_transaction *trans, struct dundi_ies *ies, char *ccontext)
Definition: pbx_dundi.c:940
unsigned char cmdresp
Definition: dundi.h:39
static struct dundi_hdr * dundi_decrypt(struct dundi_transaction *trans, unsigned char *dst, int *dstlen, struct dundi_hdr *ohdr, struct dundi_encblock *src, int srclen)
Definition: pbx_dundi.c:1406
#define NULL
Definition: resample.c:96
struct packetlist lasttrans
Definition: pbx_dundi.c:267
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares two ast_sockaddr structures.
Definition: netsock2.c:388
dundi_eid us_eid
Definition: pbx_dundi.c:250
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:274
char * q_country
Definition: dundi-parser.h:41
unsigned char oseqno
Definition: dundi.h:38
dundi_eid * eids[DUNDI_MAX_STACK+1]
Definition: dundi-parser.h:22
dundi_eid them_eid
Definition: pbx_dundi.c:251
#define ast_verb(level,...)
Definition: logger.h:463
ast_aes_decrypt_key them_dcx
Definition: pbx_dundi.c:323
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
Definition: main/utils.c:2842
int dundi_ie_append_raw(struct dundi_ie_data *ied, unsigned char ie, void *data, int datalen)
Definition: dundi-parser.c:484
static int has_permission(struct permissionlist *permlist, char *cont)
Definition: pbx_dundi.c:367
#define ast_strlen_zero(foo)
Definition: strings.h:52
unsigned char data[0]
Definition: dundi.h:112
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
#define DUNDI_IE_UNKNOWN
Definition: dundi.h:190
unsigned short flags
Definition: dundi.h:105
#define DUNDI_IE_SIGNATURE
Definition: dundi.h:195
static int cache_save_hint(dundi_eid *eidpeer, struct dundi_request *req, struct dundi_hint *hint, int expiration)
Definition: pbx_dundi.c:864
unsigned char protocol
Definition: dundi.h:104
static struct dundi_peer * any_peer
Wildcard peer.
Definition: pbx_dundi.c:352
#define AST_SCHED_DEL(sched, id)
Remove a scheduler entry.
Definition: sched.h:46
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
struct dundi_encblock * encblock
Definition: dundi-parser.h:49
static int dundidebug
Definition: pbx_dundi.c:192
#define DUNDI_MODEL_INBOUND
Definition: pbx_dundi.c:159
char * q_ipaddr
Definition: dundi-parser.h:44
char tech[10]
Definition: dundi.h:232
unsigned long keycrc32
Definition: dundi-parser.h:48
dundi_eid query_eid
Definition: pbx_dundi.c:276
#define DUNDI_IE_EID
Definition: dundi.h:182
char eid_str[20]
Definition: dundi.h:231
dundi_eid us_eid
Definition: pbx_dundi.c:308
static int default_expiration
Definition: pbx_dundi.c:199
int expiration
Definition: dundi.h:228
unsigned char ies[0]
Definition: dundi.h:41
unsigned char * encsharedkey
Definition: dundi-parser.h:46
int expiration
Definition: dundi-parser.h:33
ast_aes_encrypt_key them_ecx
Definition: pbx_dundi.c:322
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
char * q_stateprov
Definition: dundi-parser.h:40
unsigned int dynamic
Definition: pbx_dundi.c:334
static int dundi_answer_entity(struct dundi_transaction *trans, struct dundi_ies *ies, char *ccontext)
Definition: pbx_dundi.c:809
#define DUNDI_COMMAND_UNKNOWN
Definition: dundi.h:167
char number[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:275
static struct dundi_peer * find_peer(dundi_eid *eid)
Definition: pbx_dundi.c:515
int dundi_ie_append_cause(struct dundi_ie_data *ied, unsigned char ie, unsigned char cause, char *data)
Definition: dundi-parser.c:499
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
unsigned char * encsig
Definition: dundi-parser.h:47
int techint
Definition: dundi.h:229
unsigned char oseqno
Definition: pbx_dundi.c:264
int anscount
Definition: dundi-parser.h:30
#define LOG_NOTICE
Definition: logger.h:263
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: dundi.h:230
static int check_key(struct dundi_peer *peer, unsigned char *newkey, unsigned char *newsig, uint32_t keycrc32)
Definition: pbx_dundi.c:1492
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
unsigned short weight
Definition: dundi.h:106
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
struct dundi_hint_metadata * hmd
Definition: pbx_dundi.c:280
unsigned int flags
Definition: dundi.h:226
dundi_eid eid
Definition: pbx_dundi.c:304
char inkey[80]
Definition: pbx_dundi.c:309
char exten[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:233
struct dundi_peer::permissionlist permit
void dundi_showframe(struct dundi_hdr *fhi, int rx, struct ast_sockaddr *sin, int datalen)
Definition: dundi-parser.c:432
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 ast_clear_flag(p, flag)
Definition: utils.h:77
#define DUNDI_COMMAND_PRECACHERQ
Definition: dundi.h:164
int pcmodel
Definition: pbx_dundi.c:332
#define DUNDI_COMMAND_PRECACHERP
Definition: dundi.h:165
unsigned char iv[16]
Definition: dundi.h:98
char stateprov[80]
Definition: dundi.h:238
char email[80]
Definition: dundi.h:242
char * q_dept
Definition: dundi-parser.h:37
struct permissionlist include
Definition: pbx_dundi.c:307
#define DUNDI_COMMAND_REGREQ
Definition: dundi.h:169
unsigned char txenckey[256]
Definition: pbx_dundi.c:316
#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
static int handle_command_response(struct dundi_transaction *trans, struct dundi_hdr *hdr, int datalen, int encrypted)
Definition: pbx_dundi.c:1586
#define DUNDI_COMMAND_EIDQUERY
Definition: dundi.h:162
static ENTRY retval
Definition: hsearch.c:50
struct ast_sockaddr addr
Definition: pbx_dundi.c:305
dundi_eid eid
Definition: dundi.h:103
static int cache_save(dundi_eid *eidpeer, struct dundi_request *req, int start, int unaffected, int expiration, int push)
Definition: pbx_dundi.c:899
#define DUNDI_COMMAND_INVALID
Definition: dundi.h:166
char * q_phone
Definition: dundi-parser.h:43
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 DUNDI_COMMAND_DPDISCOVER
Definition: dundi.h:160
static int dundi_ack(struct dundi_transaction *trans, int final)
Definition: pbx_dundi.c:451
int dundi_parse_ies(struct dundi_ies *ies, unsigned char *data, int datalen)
Definition: dundi-parser.c:635
unsigned char iseqno
Definition: pbx_dundi.c:262
#define ast_set_flag_nonstd(p, flag)
Definition: utils.h:176
struct ast_sockaddr addr
Definition: pbx_dundi.c:246
int dundi_ie_append_byte(struct dundi_ie_data *ied, unsigned char ie, unsigned char dat)
Definition: dundi-parser.c:615
#define MAX_PACKET_SIZE
Definition: pbx_dundi.c:155
#define DUNDI_IE_ENCDATA
Definition: dundi.h:193
struct dundi_hint * hint
Definition: dundi-parser.h:29
ast_aes_decrypt_key dcx
Definition: pbx_dundi.c:253
#define DUNDI_COMMAND_NULL
Definition: dundi.h:168
#define ast_test_flag_nonstd(p, flag)
Definition: utils.h:173
char * q_email
Definition: dundi-parser.h:42
int sentfullkey
Definition: pbx_dundi.c:314
#define DUNDI_COMMAND_REGRESPONSE
Definition: dundi.h:170
unsigned char data[0]
Definition: dundi.h:107
#define DUNDI_COMMAND_CANCEL
Definition: dundi.h:171

◆ handle_frame()

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

Definition at line 2042 of file pbx_dundi.c.

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

Referenced by socket_read().

2043 {
2044  struct dundi_transaction *trans;
2045  trans = find_transaction(h, sin);
2046  if (!trans) {
2047  dundi_reject(h, sin);
2048  return 0;
2049  }
2050  /* Got a transaction, see where this header fits in */
2051  if (h->oseqno == trans->iseqno) {
2052  /* Just what we were looking for... Anything but ack increments iseqno */
2053  if (ack_trans(trans, h->iseqno) && ast_test_flag(trans, FLAG_FINAL)) {
2054  /* If final, we're done */
2055  destroy_trans(trans, 0);
2056  return 0;
2057  }
2058  if (h->cmdresp != DUNDI_COMMAND_ACK) {
2059  trans->oiseqno = trans->iseqno;
2060  trans->iseqno++;
2061  handle_command_response(trans, h, datalen, 0);
2062  }
2063  if (trans->aseqno != trans->iseqno) {
2064  dundi_ack(trans, h->cmdresp & 0x80);
2065  trans->aseqno = trans->iseqno;
2066  }
2067  /* Delete any saved last transmissions */
2068  destroy_packets(&trans->lasttrans);
2069  if (h->cmdresp & 0x80) {
2070  /* Final -- destroy now */
2071  destroy_trans(trans, 0);
2072  }
2073  } else if (h->oseqno == trans->oiseqno) {
2074  /* Last incoming sequence number -- send ACK without processing */
2075  dundi_ack(trans, 0);
2076  } else {
2077  /* Out of window -- simply drop */
2078  ast_debug(1, "Dropping packet out of window!\n");
2079  }
2080  return 0;
2081 }
unsigned char aseqno
Definition: pbx_dundi.c:265
#define ast_test_flag(p, flag)
Definition: utils.h:63
unsigned char cmdresp
Definition: dundi.h:39
struct packetlist lasttrans
Definition: pbx_dundi.c:267
unsigned char oseqno
Definition: dundi.h:38
static void destroy_trans(struct dundi_transaction *trans, int fromtimeout)
Definition: pbx_dundi.c:3203
#define DUNDI_COMMAND_ACK
Definition: dundi.h:159
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
unsigned char oiseqno
Definition: pbx_dundi.c:263
static void destroy_packets(struct packetlist *p)
Definition: pbx_dundi.c:2010
static void dundi_reject(struct dundi_hdr *h, struct ast_sockaddr *sin)
Definition: pbx_dundi.c:455
static int handle_command_response(struct dundi_transaction *trans, struct dundi_hdr *hdr, int datalen, int encrypted)
Definition: pbx_dundi.c:1586
static int ack_trans(struct dundi_transaction *trans, int iseqno)
Definition: pbx_dundi.c:2021
static int dundi_ack(struct dundi_transaction *trans, int final)
Definition: pbx_dundi.c:451
unsigned char iseqno
Definition: pbx_dundi.c:262
static struct dundi_transaction * find_transaction(struct dundi_hdr *hdr, struct ast_sockaddr *sin)
Definition: pbx_dundi.c:412
unsigned char iseqno
Definition: dundi.h:37

◆ has_permission()

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

Definition at line 367 of file pbx_dundi.c.

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

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

368 {
369  struct permission *perm;
370  int res = 0;
371 
372  AST_LIST_TRAVERSE(permlist, perm, list) {
373  if (!strcasecmp(perm->name, "all") || !strcasecmp(perm->name, cont))
374  res = perm->allow;
375  }
376 
377  return res;
378 }
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
char name[0]
Definition: pbx_dundi.c:218
struct permission::@435 list

◆ load_module()

static int load_module ( void  )
static

Definition at line 5169 of file pbx_dundi.c.

References ARRAY_LEN, ast_bind(), ast_cli_register_multiple, ast_custom_function_register, ast_log, AST_MODFLAG_DEFAULT, AST_MODULE_INFO(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, AST_MODULE_SUPPORT_EXTENDED, ast_register_switch(), ast_sched_context_create(), ast_set_qos(), ast_sockaddr_is_ipv4(), ast_sockaddr_is_ipv6(), ast_sockaddr_isnull(), ast_sockaddr_setnull(), ast_sockaddr_stringify(), ast_verb, ASTERISK_GPL_KEY, dundi_debug_output(), dundi_error_output(), dundi_set_error(), dundi_set_output(), errno, io_context_create(), LOG_ERROR, reload(), set_config(), start_network_thread(), and unload_module().

5170 {
5171  struct ast_sockaddr sin;
5172  struct ast_sockaddr sin2;
5173 
5176 
5177  /* Make a UDP socket */
5178  io = io_context_create();
5180 
5181  if (!io || !sched) {
5182  goto declined;
5183  }
5184 
5185  ast_sockaddr_setnull(&sin);
5186  ast_sockaddr_setnull(&sin2);
5187 
5188  if (set_config("dundi.conf", &sin, 0, &sin2)) {
5189  goto declined;
5190  }
5191 
5192  if (!ast_sockaddr_isnull(&sin2)) {
5193  if ((ast_sockaddr_is_ipv4(&sin) == ast_sockaddr_is_ipv4(&sin2)) || (ast_sockaddr_is_ipv6(&sin) == ast_sockaddr_is_ipv6(&sin2))) {
5194  ast_log(LOG_ERROR, "bindaddr & bindaddr2 should be different IP protocols.\n");
5195  goto declined;
5196  }
5197 
5198  /*bind netsocket to ipv4, netsocket2 to ipv6 */
5199 
5200  netsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
5201  netsocket2 = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);
5202  if (netsocket < 0 || netsocket2 < 0) {
5203  ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno));
5204  goto declined;
5205  }
5206  if (ast_sockaddr_is_ipv4(&sin)) {
5207  if (ast_bind(netsocket, &sin)) {
5208  ast_log(LOG_ERROR, "Unable to bind to %s : %s\n",
5209  ast_sockaddr_stringify(&sin), strerror(errno));
5210  goto declined;
5211  }
5212  if (ast_bind(netsocket2, &sin2)) {
5213  ast_log(LOG_ERROR, "Unable to bind to %s : %s\n",
5214  ast_sockaddr_stringify(&sin2), strerror(errno));
5215  goto declined;
5216  }
5217  } else {
5218  if (ast_bind(netsocket, &sin2)) {
5219  ast_log(LOG_ERROR, "Unable to bind to %s : %s\n",
5220  ast_sockaddr_stringify(&sin2), strerror(errno));
5221  goto declined;
5222  }
5223  if (ast_bind(netsocket2, &sin)) {
5224  ast_log(LOG_ERROR, "Unable to bind to %s : %s\n",
5225  ast_sockaddr_stringify(&sin), strerror(errno));
5226  goto declined;
5227  }
5228  }
5229  ast_set_qos(netsocket, tos, 0, "DUNDi");
5230  ast_set_qos(netsocket2, tos, 0, "DUNDi");
5231  } else {
5232  if (ast_sockaddr_is_ipv6(&sin)) {
5233  netsocket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);
5234  } else {
5235  netsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
5236  }
5237  if (netsocket < 0) {
5238  ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno));
5239  goto declined;
5240  }
5241  if (ast_bind(netsocket, &sin)) {
5242  ast_log(LOG_ERROR, "Unable to bind to %s : %s\n",
5243  ast_sockaddr_stringify(&sin), strerror(errno));
5244  goto declined;
5245  }
5246  ast_set_qos(netsocket, tos, 0, "DUNDi");
5247  }
5248 
5249  if (start_network_thread()) {
5250  ast_log(LOG_ERROR, "Unable to start network thread\n");
5251  goto declined;
5252  }
5253 
5256  ast_log(LOG_ERROR, "Unable to register DUNDi switch\n");
5260 
5261  ast_verb(2, "DUNDi Ready and Listening on %s\n", ast_sockaddr_stringify(&sin));
5262  if (!ast_sockaddr_isnull(&sin2))
5263  ast_verb(2, "DUNDi Ready and Listening on %s\n", ast_sockaddr_stringify(&sin2));
5264 
5265  return AST_MODULE_LOAD_SUCCESS;
5266 
5267 declined:
5268  unload_module();
5269  return AST_MODULE_LOAD_DECLINE;
5270 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static int set_config(char *config_file, struct ast_sockaddr *sin, int reload, struct ast_sockaddr *sin2)
Definition: pbx_dundi.c:4937
void dundi_set_error(void(*func)(const char *))
Definition: dundi-parser.c:630
static int start_network_thread(void)
Definition: pbx_dundi.c:2296
static struct io_context * io
Definition: pbx_dundi.c:184
Definition: sched.c:76
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
Socket address structure.
Definition: netsock2.h:97
int ast_bind(int sockfd, const struct ast_sockaddr *addr)
Wrapper around bind(2) that uses struct ast_sockaddr.
Definition: netsock2.c:590
#define ast_verb(level,...)
Definition: logger.h:463
static void ast_sockaddr_setnull(struct ast_sockaddr *addr)
Sets address addr to null.
Definition: netsock2.h:140
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
static int netsocket
Definition: pbx_dundi.c:186
#define ast_log
Definition: astobj2.c:42
void dundi_set_output(void(*func)(const char *))
Definition: dundi-parser.c:625
static void dundi_debug_output(const char *data)
Definition: pbx_dundi.c:356
static struct ast_custom_function dundi_function
Definition: pbx_dundi.c:4186
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
Definition: sched.c:236
#define LOG_ERROR
Definition: logger.h:285
int ast_set_qos(int sockfd, int tos, int cos, const char *desc)
Set type of service.
Definition: netsock2.c:621
int errno
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
static unsigned int tos
Definition: pbx_dundi.c:191
int ast_register_switch(struct ast_switch *sw)
Register an alternative dialplan switch.
Definition: pbx_switch.c:58
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static struct ast_cli_entry cli_dundi[]
Definition: pbx_dundi.c:3119
static void dundi_error_output(const char *data)
Definition: pbx_dundi.c:362
static int unload_module(void)
Definition: pbx_dundi.c:5099
int ast_sockaddr_is_ipv4(const struct ast_sockaddr *addr)
Determine if the address is an IPv4 address.
Definition: netsock2.c:497
static struct ast_custom_function dundi_query_function
Definition: pbx_dundi.c:4274
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1508
int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
Determine if this is an IPv6 address.
Definition: netsock2.c:524
static struct ast_switch dundi_switch
Definition: pbx_dundi.c:4892
static int netsocket2
Definition: pbx_dundi.c:187
static struct ast_custom_function dundi_result_function
Definition: pbx_dundi.c:4348
struct io_context * io_context_create(void)
Creates a context Create a context for I/O operations Basically mallocs an IO structure and sets up s...
Definition: io.c:81

◆ load_password()

static void load_password ( void  )
static

Definition at line 2138 of file pbx_dundi.c.

References ast_copy_string(), ast_db_get(), ast_get_time_t(), build_secret(), DUNDI_SECRET_TIME, last, NULL, save_secret(), and tmp().

Referenced by set_config().

2139 {
2140  char *current=NULL;
2141  char *last=NULL;
2142  char tmp[256];
2143  time_t expired;
2144 
2145  ast_db_get(secretpath, "secretexpiry", tmp, sizeof(tmp));
2146  if (!ast_get_time_t(tmp, &expired, 0, NULL)) {
2147  ast_db_get(secretpath, "secret", tmp, sizeof(tmp));
2148  current = strchr(tmp, ';');
2149  if (!current)
2150  current = tmp;
2151  else {
2152  *current = '\0';
2153  current++;
2154  };
2155  if ((time(NULL) - expired) < 0) {
2156  if ((expired - time(NULL)) > DUNDI_SECRET_TIME)
2157  expired = time(NULL) + DUNDI_SECRET_TIME;
2158  } else if ((time(NULL) - (expired + DUNDI_SECRET_TIME)) < 0) {
2159  last = current;
2160  current = NULL;
2161  } else {
2162  last = NULL;
2163  current = NULL;
2164  }
2165  }
2166  if (current) {
2167  /* Current key is still valid, just setup rotatation properly */
2168  ast_copy_string(cursecret, current, sizeof(cursecret));
2169  rotatetime = expired;
2170  } else {
2171  /* Current key is out of date, rotate or eliminate all together */
2172  build_secret(cursecret, sizeof(cursecret));
2173  save_secret(cursecret, last);
2174  }
2175 }
static int tmp()
Definition: bt_open.c:389
#define NULL
Definition: resample.c:96
static char secretpath[80]
Definition: pbx_dundi.c:208
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
static void save_secret(const char *newkey, const char *oldkey)
Definition: pbx_dundi.c:2125
struct sla_ringing_trunk * last
Definition: app_meetme.c:1092
#define DUNDI_SECRET_TIME
Definition: pbx_dundi.c:181
static void build_secret(char *secret, int seclen)
Definition: pbx_dundi.c:2110
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
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

◆ mark_mappings()

static void mark_mappings ( void  )
static

Definition at line 4363 of file pbx_dundi.c.

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

Referenced by set_config(), and unload_module().

4364 {
4365  struct dundi_mapping *map;
4366 
4367  AST_LIST_LOCK(&peers);
4368  AST_LIST_TRAVERSE(&mappings, map, list) {
4369  map->dead = 1;
4370  }
4372 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
static int * map
Definition: misdn_config.c:438
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
struct dundi_mapping::@442 list
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490

◆ mark_peers()

static void mark_peers ( void  )
static

Definition at line 4353 of file pbx_dundi.c.

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

Referenced by set_config(), and unload_module().

4354 {
4355  struct dundi_peer *peer;
4356  AST_LIST_LOCK(&peers);
4357  AST_LIST_TRAVERSE(&peers, peer, list) {
4358  peer->dead = 1;
4359  }
4361 }
struct dundi_peer::@443 list
#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

◆ model2str()

static char* model2str ( int  model)
static

Definition at line 2403 of file pbx_dundi.c.

References DUNDI_MODEL_INBOUND, DUNDI_MODEL_OUTBOUND, and DUNDI_MODEL_SYMMETRIC.

Referenced by dundi_show_peer(), and dundi_show_peers().

2404 {
2405  switch(model) {
2406  case DUNDI_MODEL_INBOUND:
2407  return "Inbound";
2408  case DUNDI_MODEL_OUTBOUND:
2409  return "Outbound";
2410  case DUNDI_MODEL_SYMMETRIC:
2411  return "Symmetric";
2412  default:
2413  return "Unknown";
2414  }
2415 }
#define DUNDI_MODEL_SYMMETRIC
Definition: pbx_dundi.c:161
#define DUNDI_MODEL_INBOUND
Definition: pbx_dundi.c:159
#define DUNDI_MODEL_OUTBOUND
Definition: pbx_dundi.c:160

◆ network_thread()

static void* network_thread ( void *  ignore)
static

Definition at line 2194 of file pbx_dundi.c.

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

Referenced by start_network_thread().

2195 {
2196  /* Our job is simple: Send queued messages, retrying if necessary. Read frames
2197  from the network, and queue them for delivery to the channels */
2198  int res;
2199  /* Establish I/O callback for socket read */
2200  int *socket_read_id = ast_io_add(io, netsocket, socket_read, AST_IO_IN, &netsocket);
2201  int *socket_read_id2 = NULL;
2202  if (netsocket2 >= 0) {
2203  socket_read_id2 = ast_io_add(io, netsocket2, socket_read, AST_IO_IN, &netsocket2);
2204  }
2205 
2206  while (!dundi_shutdown) {
2207  res = ast_sched_wait(sched);
2208  if ((res > 1000) || (res < 0))
2209  res = 1000;
2210  res = ast_io_wait(io, res);
2211  if (res >= 0) {
2212  AST_LIST_LOCK(&peers);
2215  }
2216  check_password();
2217  }
2218 
2219  ast_io_remove(io, socket_read_id);
2220 
2221  if (socket_read_id2) {
2222  ast_io_remove(io, socket_read_id2);
2223  }
2224 
2225  return NULL;
2226 }
int ast_io_wait(struct io_context *ioc, int howlong)
Waits for IO.
Definition: io.c:278
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
int ast_sched_runq(struct ast_sched_context *con)
Runs the queue.
Definition: sched.c:755
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static struct io_context * io
Definition: pbx_dundi.c:184
#define AST_IO_IN
Definition: io.h:34
Definition: sched.c:76
int * ast_io_add(struct io_context *ioc, int fd, ast_io_cb callback, short events, void *data)
Adds an IO context.
Definition: io.c:162
#define NULL
Definition: resample.c:96
static int netsocket
Definition: pbx_dundi.c:186
static void check_password(void)
Definition: pbx_dundi.c:2177
static int dundi_shutdown
Definition: pbx_dundi.c:213
int ast_io_remove(struct io_context *ioc, int *id)
Removes an IO context.
Definition: io.c:245
int ast_sched_wait(struct ast_sched_context *con) attribute_warn_unused_result
Determines number of seconds until the next outstanding event to take place.
Definition: sched.c:431
static int socket_read(int *id, int fd, short events, void *sock)
Definition: pbx_dundi.c:2083
static int netsocket2
Definition: pbx_dundi.c:187

◆ optimize_transactions()

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

Definition at line 3584 of file pbx_dundi.c.

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

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

3585 {
3586  /* Minimize the message propagation through DUNDi by
3587  alerting the network to hops which should be not be considered */
3588  struct dundi_transaction *trans;
3589  struct dundi_peer *peer;
3590  dundi_eid tmp;
3591  int x;
3592  int needpush;
3593 
3594  AST_LIST_LOCK(&peers);
3595  AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) {
3596  /* Pop off the true root */
3597  if (trans->eidcount) {
3598  tmp = trans->eids[--trans->eidcount];
3599  needpush = 1;
3600  } else {
3601  tmp = trans->us_eid;
3602  needpush = 0;
3603  }
3604 
3605  AST_LIST_TRAVERSE(&peers, peer, list) {
3606  if (ast_eid_cmp(&peer->eid, &empty_eid) && /* peer's eid is not empty (in case of dynamic peers) */
3607  (peer->lastms > -1) && /* peer is reachable */
3608  has_permission(&peer->include, dr->dcontext) && /* peer has destination context */
3609  ast_eid_cmp(&peer->eid, &trans->them_eid) && /* peer is not transaction endpoint */
3610  (peer->order <= order)) {
3611  /* For each other transaction, make sure we don't
3612  ask this EID about the others if they're not
3613  already in the list */
3614  if (!ast_eid_cmp(&tmp, &peer->eid))
3615  x = -1;
3616  else {
3617  for (x=0;x<trans->eidcount;x++) {
3618  if (!ast_eid_cmp(&trans->eids[x], &peer->eid))
3619  break;
3620  }
3621  }
3622  if (x == trans->eidcount) {
3623  /* Nope not in the list, if needed, add us at the end since we're the source */
3624  if (trans->eidcount < DUNDI_MAX_STACK - needpush) {
3625  trans->eids[trans->eidcount++] = peer->eid;
3626  /* Need to insert the real root (or us) at the bottom now as
3627  a requirement now. */
3628  needpush = 1;
3629  }
3630  }
3631  }
3632  }
3633  /* If necessary, push the true root back on the end */
3634  if (needpush)
3635  trans->eids[trans->eidcount++] = tmp;
3636  }
3638 
3639  return 0;
3640 }
struct dundi_peer::@443 list
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
dundi_eid eids[DUNDI_MAX_STACK+1]
Definition: pbx_dundi.c:248
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static int tmp()
Definition: bt_open.c:389
dundi_eid us_eid
Definition: pbx_dundi.c:250
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:274
dundi_eid them_eid
Definition: pbx_dundi.c:251
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 lastms
Definition: pbx_dundi.c:335
static int has_permission(struct permissionlist *permlist, char *cont)
Definition: pbx_dundi.c:367
integer order
Definition: analys.c:66
static dundi_eid empty_eid
Definition: pbx_dundi.c:212
#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 dundi_request::@440 trans
#define DUNDI_MAX_STACK
Definition: dundi-parser.h:18
struct permissionlist include
Definition: pbx_dundi.c:307

◆ populate_addr()

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

Definition at line 4588 of file pbx_dundi.c.

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

Referenced by build_peer().

4589 {
4590  char data[256];
4591  char *c;
4592  int port, expire;
4593  char eid_str[20];
4594  ast_eid_to_str(eid_str, sizeof(eid_str), eid);
4595  if (!ast_db_get("dundi/dpeers", eid_str, data, sizeof(data))) {
4596  /*
4597  * data is in the form:
4598  * IPv6 address: [ffff:ffff::ffff:ffff]:port:expire
4599  * IPv4 address: a.b.c.d:port:expire
4600  */
4601  c = data;
4602  if (*c == '[') {
4603  /* Need to skip over the IPv6 address. */
4604  c = strchr(c, ']');
4605  }
4606  if (c) {
4607  c = strchr(c, ':');
4608  }
4609  if (c) {
4610  *c = '\0';
4611  c++;
4612  if (sscanf(c, "%5d:%30d", &port, &expire) == 2) {
4613  /* Got it! */
4614  struct ast_sockaddr *addrs;
4615 
4616  if (ast_sockaddr_resolve(&addrs, data, PARSE_PORT_FORBID, AF_UNSPEC) > 0){
4617  ast_sockaddr_copy(&peer->addr, &addrs[0]);
4618  ast_free(addrs);
4619  }
4620  ast_sockaddr_set_port(&peer->addr, port);
4621  peer->registerexpire = ast_sched_add(sched, (expire + 10) * 1000, do_register_expire, peer);
4622  }
4623  }
4624  }
4625 }
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 do_register_expire(const void *data)
Definition: pbx_dundi.c:1321
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
Definition: sched.c:76
int registerexpire
Definition: pbx_dundi.c:325
static struct test_val c
Socket address structure.
Definition: netsock2.h:97
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:537
#define ast_free(a)
Definition: astmm.h:182
int ast_db_get(const char *family, const char *key, char *value, int valuelen)
Get key value specified by family/key.
Definition: main/db.c:412
int ast_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
struct ast_sockaddr addr
Definition: pbx_dundi.c:305
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

◆ precache_trans()

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

Definition at line 3437 of file pbx_dundi.c.

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

Referenced by precache_transactions().

3438 {
3439  struct dundi_ie_data ied;
3440  int x, res;
3441  int max = 999999;
3442  int expiration = dundi_cache_time;
3443  int ouranswers=0;
3444  dundi_eid *avoid[1] = { NULL, };
3445  int direct[1] = { 0, };
3446  struct dundi_result dr[MAX_RESULTS];
3447  struct dundi_hint_metadata hmd;
3448  if (!trans->parent) {
3449  ast_log(LOG_WARNING, "Tried to discover a transaction with no parent?!?\n");
3450  return -1;
3451  }
3452  memset(&hmd, 0, sizeof(hmd));
3453  memset(&dr, 0, sizeof(dr));
3454  /* Look up the answers we're going to include */
3455  for (x=0;x<mapcount;x++)
3456  ouranswers = dundi_lookup_local(dr, maps + x, trans->parent->number, &trans->us_eid, ouranswers, &hmd);
3457  if (ouranswers < 0)
3458  ouranswers = 0;
3459  for (x=0;x<ouranswers;x++) {
3460  if (dr[x].weight < max)
3461  max = dr[x].weight;
3462  }
3463  if (max) {
3464  /* If we do not have a canonical result, keep looking */
3465  res = dundi_lookup_internal(dr + ouranswers, MAX_RESULTS - ouranswers, NULL, trans->parent->dcontext, trans->parent->number, trans->ttl, 1, &hmd, &expiration, 0, 1, &trans->them_eid, avoid, direct);
3466  if (res > 0) {
3467  /* Append answer in result */
3468  ouranswers += res;
3469  }
3470  }
3471 
3472  if (ouranswers > 0) {
3473  *foundanswers += ouranswers;
3474  memset(&ied, 0, sizeof(ied));
3476  if (!dundi_eid_zero(&trans->us_eid))
3477  dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid);
3478  for (x=0;x<trans->eidcount;x++)
3479  dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->eids[x]);
3482  dundi_ie_append_short(&ied, DUNDI_IE_TTL, trans->ttl);
3483  for (x=0;x<ouranswers;x++) {
3484  /* Add answers */
3485  if (dr[x].expiration && (expiration > dr[x].expiration))
3486  expiration = dr[x].expiration;
3487  dundi_ie_append_answer(&ied, DUNDI_IE_ANSWER, &dr[x].eid, dr[x].techint, dr[x].flags, dr[x].weight, dr[x].dest);
3488  }
3489  dundi_ie_append_hint(&ied, DUNDI_IE_HINT, hmd.flags, hmd.exten);
3490  dundi_ie_append_short(&ied, DUNDI_IE_EXPIRATION, expiration);
3491  if (trans->autokilltimeout)
3492  trans->autokillid = ast_sched_add(sched, trans->autokilltimeout, do_autokill, trans);
3493  if (expiration < *minexp)
3494  *minexp = expiration;
3495  return dundi_send(trans, DUNDI_COMMAND_PRECACHERQ, 0, 0, &ied);
3496  } else {
3497  /* Oops, nothing to send... */
3498  destroy_trans(trans, 0);
3499  return 0;
3500  }
3501 }
static float dr[4]
Definition: tdd.c:58
#define DUNDI_IE_EXPIRATION
Definition: dundi.h:189
static int dundi_lookup_local(struct dundi_result *dr, struct dundi_mapping *map, char *called_number, dundi_eid *us_eid, int anscnt, struct dundi_hint_metadata *hmd)
Definition: pbx_dundi.c:578
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
static int dundi_cache_time
Definition: pbx_dundi.c:196
dundi_eid eids[DUNDI_MAX_STACK+1]
Definition: pbx_dundi.c:248
#define LOG_WARNING
Definition: logger.h:274
#define MAX_RESULTS
Definition: pbx_dundi.c:153
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
int dundi_ie_append_hint(struct dundi_ie_data *ied, unsigned char ie, unsigned short flags, char *data)
Definition: dundi-parser.c:518
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
dundi_eid us_eid
Definition: pbx_dundi.c:250
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:274
#define DUNDI_IE_VERSION
Definition: dundi.h:188
static void destroy_trans(struct dundi_transaction *trans, int fromtimeout)
Definition: pbx_dundi.c:3203
dundi_eid them_eid
Definition: pbx_dundi.c:251
An Entity ID is essentially a MAC address, brief and unique.
Definition: utils.h:786
#define ast_log
Definition: astobj2.c:42
#define DUNDI_IE_EID
Definition: dundi.h:182
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
char weight
#define DUNDI_IE_CALLED_CONTEXT
Definition: dundi.h:183
#define DUNDI_IE_HINT
Definition: dundi.h:197
#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
unsigned short flags
Definition: pbx_dundi.c:232
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
#define DUNDI_COMMAND_PRECACHERQ
Definition: dundi.h:164
int dundi_eid_zero(dundi_eid *eid)
Definition: dundi-parser.c:82
#define DUNDI_IE_ANSWER
Definition: dundi.h:186
int dundi_ie_append_answer(struct dundi_ie_data *ied, unsigned char ie, dundi_eid *eid, unsigned char protocol, unsigned short flags, unsigned short weight, char *data)
Definition: dundi-parser.c:559
#define DUNDI_IE_TTL
Definition: dundi.h:187
#define max(a, b)
Definition: f2c.h:198

◆ precache_transactions()

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

Definition at line 3536 of file pbx_dundi.c.

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

Referenced by dundi_precache_internal().

3537 {
3538  struct dundi_transaction *trans;
3539 
3540  /* Mark all as "in thread" so they don't disappear */
3541  AST_LIST_LOCK(&peers);
3542  AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) {
3543  if (trans->thread)
3544  ast_log(LOG_WARNING, "This shouldn't happen, really...\n");
3545  trans->thread = 1;
3546  }
3548 
3549  AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) {
3550  if (!ast_test_flag(trans, FLAG_DEAD))
3551  precache_trans(trans, maps, mapcount, expiration, foundanswers);
3552  }
3553 
3554  /* Cleanup any that got destroyed in the mean time */
3555  AST_LIST_LOCK(&peers);
3557  trans->thread = 0;
3558  if (ast_test_flag(trans, FLAG_DEAD)) {
3559  ast_debug(1, "Our transaction went away!\n");
3560  /* This is going to remove the transaction from the dundi_request's list, as well
3561  * as the global transactions list */
3562  destroy_trans(trans, 0);
3563  }
3564  }
3567 
3568  return 0;
3569 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define LOG_WARNING
Definition: logger.h:274
#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
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
static int precache_trans(struct dundi_transaction *trans, struct dundi_mapping *maps, int mapcount, int *minexp, int *foundanswers)
Definition: pbx_dundi.c:3437
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
struct dundi_transaction::@438 parentlist
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct dundi_request::@440 trans
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528

◆ process_clearcache()

static void* process_clearcache ( void *  ignore)
static

Definition at line 2228 of file pbx_dundi.c.

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

Referenced by start_network_thread().

2229 {
2230  struct ast_db_entry *db_entry, *db_tree;
2231  int striplen = sizeof("/dundi/cache");
2232  time_t now;
2233 
2234  while (!dundi_shutdown) {
2235  pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
2236 
2237  time(&now);
2238 
2239  db_entry = db_tree = ast_db_gettree("dundi/cache", NULL);
2240  for (; db_entry; db_entry = db_entry->next) {
2241  time_t expiry;
2242 
2243  if (!ast_get_time_t(db_entry->data, &expiry, 0, NULL)) {
2244  if (expiry < now) {
2245  ast_debug(1, "clearing expired DUNDI cache entry: %s\n", db_entry->key);
2246  ast_db_del("dundi/cache", db_entry->key + striplen);
2247  }
2248  }
2249  }
2250  ast_db_freetree(db_tree);
2251 
2252  pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
2253  pthread_testcancel();
2254  sleep(60);
2255  pthread_testcancel();
2256  }
2257 
2258  return NULL;
2259 }
void ast_db_freetree(struct ast_db_entry *entry)
Free structure created by ast_db_gettree()
Definition: main/db.c:598
#define NULL
Definition: resample.c:96
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
struct ast_db_entry * next
Definition: astdb.h:32
struct ast_db_entry * ast_db_gettree(const char *family, const char *keytree)
Get a list of values within the astdb tree.
Definition: main/db.c:531
Definition: astdb.h:31
char data[0]
Definition: astdb.h:34
static int dundi_shutdown
Definition: pbx_dundi.c:213
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: main/db.c:429
char * key
Definition: astdb.h:33

◆ process_precache()

static void* process_precache ( void *  ign)
static

Definition at line 2261 of file pbx_dundi.c.

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

Referenced by start_network_thread().

2262 {
2263  struct dundi_precache_queue *qe;
2264  time_t now;
2265  char context[256];
2266  char number[256];
2267  int run;
2268 
2269  while (!dundi_shutdown) {
2270  time(&now);
2271  run = 0;
2272  AST_LIST_LOCK(&pcq);
2273  if ((qe = AST_LIST_FIRST(&pcq))) {
2274  if (!qe->expiration) {
2275  /* Gone... Remove... */
2277  ast_free(qe);
2278  } else if (qe->expiration < now) {
2279  /* Process this entry */
2280  qe->expiration = 0;
2281  ast_copy_string(context, qe->context, sizeof(context));
2282  ast_copy_string(number, qe->number, sizeof(number));
2283  run = 1;
2284  }
2285  }
2286  AST_LIST_UNLOCK(&pcq);
2287  if (run) {
2288  dundi_precache(context, number);
2289  } else
2290  sleep(1);
2291  }
2292 
2293  return NULL;
2294 }
Definition: pbx_dundi.c:342
#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
#define NULL
Definition: resample.c:96
Number structure.
Definition: app_followme.c:154
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
int dundi_precache(const char *context, const char *number)
Pre-cache to push upstream peers.
Definition: pbx_dundi.c:4068
#define ast_free(a)
Definition: astmm.h:182
struct dundi_precache_queue::@437 list
static int dundi_shutdown
Definition: pbx_dundi.c:213
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

◆ prune_mappings()

static void prune_mappings ( void  )
static

Definition at line 4427 of file pbx_dundi.c.

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

Referenced by set_config(), and unload_module().

4428 {
4429  struct dundi_mapping *map;
4430 
4431  AST_LIST_LOCK(&peers);
4433  if (map->dead) {
4435  destroy_map(map);
4436  }
4437  }
4440 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
static void destroy_map(struct dundi_mapping *map)
Definition: pbx_dundi.c:4406
static int * map
Definition: misdn_config.c:438
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
struct dundi_mapping::@442 list
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:556
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528

◆ prune_peers()

static void prune_peers ( void  )
static

Definition at line 4412 of file pbx_dundi.c.

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

Referenced by set_config(), and unload_module().

4413 {
4414  struct dundi_peer *peer;
4415 
4416  AST_LIST_LOCK(&peers);
4418  if (peer->dead) {
4420  destroy_peer(peer);
4421  }
4422  }
4425 }
struct dundi_peer::@443 list
#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_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:556
static void destroy_peer(struct dundi_peer *peer)
Definition: pbx_dundi.c:4382
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528

◆ qualify_peer()

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

Definition at line 4565 of file pbx_dundi.c.

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

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

4566 {
4567  int when;
4568  AST_SCHED_DEL(sched, peer->qualifyid);
4569  if (peer->qualtrans)
4570  destroy_trans(peer->qualtrans, 0);
4571  peer->qualtrans = NULL;
4572  if (peer->maxms > 0) {
4573  when = 60000;
4574  if (peer->lastms < 0)
4575  when = 10000;
4576  if (schedonly)
4577  when = 5000;
4578  peer->qualifyid = ast_sched_add(sched, when, do_qualify, peer);
4579  if (!schedonly)
4580  peer->qualtrans = create_transaction(peer);
4581  if (peer->qualtrans) {
4582  peer->qualtx = ast_tvnow();
4585  }
4586  }
4587 }
int qualifyid
Definition: pbx_dundi.c:313
#define ast_set_flag(p, flag)
Definition: utils.h:70
Definition: sched.c:76
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
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
static void destroy_trans(struct dundi_transaction *trans, int fromtimeout)
Definition: pbx_dundi.c:3203
int lastms
Definition: pbx_dundi.c:335
struct timeval qualtx
Definition: pbx_dundi.c:337
static struct dundi_transaction * create_transaction(struct dundi_peer *p)
Definition: pbx_dundi.c:3137
#define AST_SCHED_DEL(sched, id)
Remove a scheduler entry.
Definition: sched.h:46
struct dundi_transaction * qualtrans
Definition: pbx_dundi.c:330
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
static int do_qualify(const void *data)
Definition: pbx_dundi.c:4557
#define DUNDI_COMMAND_NULL
Definition: dundi.h:168

◆ query_transactions()

static int query_transactions ( struct dundi_request dr)
static

Definition at line 3571 of file pbx_dundi.c.

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

Referenced by dundi_query_eid_internal().

3572 {
3573  struct dundi_transaction *trans;
3574 
3575  AST_LIST_LOCK(&peers);
3576  AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) {
3577  dundi_query(trans);
3578  }
3580 
3581  return 0;
3582 }
#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_query(struct dundi_transaction *trans)
Definition: pbx_dundi.c:3503
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct dundi_request::@440 trans

◆ register_request()

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

Definition at line 3758 of file pbx_dundi.c.

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

Referenced by dundi_lookup_internal().

3759 {
3760  struct dundi_request *cur;
3761  int res=0;
3762  char eid_str[20];
3763  AST_LIST_LOCK(&peers);
3764  AST_LIST_TRAVERSE(&requests, cur, list) {
3765  ast_debug(1, "Checking '%s@%s' vs '%s@%s'\n", cur->dcontext, cur->number,
3766  dr->dcontext, dr->number);
3767  if (!strcasecmp(cur->dcontext, dr->dcontext) &&
3768  !strcasecmp(cur->number, dr->number) &&
3769  (!ast_eid_cmp(&cur->root_eid, &dr->root_eid) || (cur->crc32 == dr->crc32))) {
3770  ast_debug(1, "Found existing query for '%s@%s' for '%s' crc '%08x'\n",
3771  cur->dcontext, cur->number, ast_eid_to_str(eid_str, sizeof(eid_str), &cur->root_eid), cur->crc32);
3772  *pending = cur;
3773  res = 1;
3774  break;
3775  }
3776  }
3777  if (!res) {
3778  ast_debug(1, "Registering request for '%s@%s' on behalf of '%s' crc '%08x'\n",
3779  dr->number, dr->dcontext, ast_eid_to_str(eid_str, sizeof(eid_str), &dr->root_eid), dr->crc32);
3780  /* Go ahead and link us in since nobody else is searching for this */
3782  *pending = NULL;
3783  }
3785  return res;
3786 }
#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 NULL
Definition: resample.c:96
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
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
char number[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:275
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
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
dundi_eid root_eid
Definition: pbx_dundi.c:277
struct dundi_request::@441 list

◆ reload()

static int reload ( void  )
static

Definition at line 5155 of file pbx_dundi.c.

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

Referenced by load_module().

5156 {
5157  struct ast_sockaddr sin;
5158  struct ast_sockaddr sin2;
5159 
5160  ast_sockaddr_setnull(&sin);
5161  ast_sockaddr_setnull(&sin2);
5162 
5163  if (set_config("dundi.conf", &sin, 1, &sin2))
5164  return AST_MODULE_LOAD_FAILURE;
5165 
5166  return AST_MODULE_LOAD_SUCCESS;
5167 }
static int set_config(char *config_file, struct ast_sockaddr *sin, int reload, struct ast_sockaddr *sin2)
Definition: pbx_dundi.c:4937
Socket address structure.
Definition: netsock2.h:97
static void ast_sockaddr_setnull(struct ast_sockaddr *addr)
Sets address addr to null.
Definition: netsock2.h:140
Module could not be loaded properly.
Definition: module.h:102

◆ reschedule_precache()

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

Definition at line 3937 of file pbx_dundi.c.

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

Referenced by dundi_precache_full(), and dundi_precache_internal().

3938 {
3939  struct dundi_precache_queue *qe, *prev;
3940 
3941  AST_LIST_LOCK(&pcq);
3943  if (!strcmp(number, qe->number) && !strcasecmp(context, qe->context)) {
3945  break;
3946  }
3947  }
3949  if (!qe) {
3950  int len = sizeof(*qe);
3951  int num_len = strlen(number) + 1;
3952  int context_len = strlen(context) + 1;
3953  if (!(qe = ast_calloc(1, len + num_len + context_len))) {
3954  AST_LIST_UNLOCK(&pcq);
3955  return;
3956  }
3957  strcpy(qe->number, number);
3958  qe->context = qe->number + num_len + 1;
3959  ast_copy_string(qe->context, context, context_len);
3960  }
3961  time(&qe->expiration);
3962  qe->expiration += expiration;
3963  if ((prev = AST_LIST_FIRST(&pcq))) {
3964  while (AST_LIST_NEXT(prev, list) && ((AST_LIST_NEXT(prev, list))->expiration <= qe->expiration))
3965  prev = AST_LIST_NEXT(prev, list);
3966  AST_LIST_INSERT_AFTER(&pcq, prev, qe, list);
3967  } else
3968  AST_LIST_INSERT_HEAD(&pcq, qe, list);
3969  AST_LIST_UNLOCK(&pcq);
3970 }
Definition: pbx_dundi.c:342
#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
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:438
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
#define AST_LIST_INSERT_AFTER(head, listelm, elm, field)
Inserts a list entry after a given entry.
Definition: linkedlists.h:694
Number structure.
Definition: app_followme.c:154
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:556
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#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_precache_queue::@437 list
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ rescomp()

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

Definition at line 2439 of file pbx_dundi.c.

References a, b, and dundi_result::weight.

Referenced by sort_results().

2440 {
2441  const struct dundi_result *resa, *resb;
2442  resa = a;
2443  resb = b;
2444  if (resa->weight < resb->weight)
2445  return -1;
2446  if (resa->weight > resb->weight)
2447  return 1;
2448  return 0;
2449 }
int weight
Definition: dundi.h:227
static struct test_val b
static struct test_val a

◆ reset_transaction()

static int reset_transaction ( struct dundi_transaction trans)
static

Definition at line 499 of file pbx_dundi.c.

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

Referenced by handle_command_response().

500 {
501  int tid;
502  tid = get_trans_id();
503  if (tid < 1)
504  return -1;
505  trans->strans = tid;
506  trans->dtrans = 0;
507  trans->iseqno = 0;
508  trans->oiseqno = 0;
509  trans->oseqno = 0;
510  trans->aseqno = 0;
511  ast_clear_flag(trans, FLAG_FINAL);
512  return 0;
513 }
unsigned char aseqno
Definition: pbx_dundi.c:265
unsigned char oiseqno
Definition: pbx_dundi.c:263
static int get_trans_id(void)
Definition: pbx_dundi.c:480
unsigned short strans
Definition: pbx_dundi.c:260
unsigned char oseqno
Definition: pbx_dundi.c:264
unsigned short dtrans
Definition: pbx_dundi.c:261
#define ast_clear_flag(p, flag)
Definition: utils.h:77
unsigned char iseqno
Definition: pbx_dundi.c:262

◆ save_secret()

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

Definition at line 2125 of file pbx_dundi.c.

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

Referenced by check_password(), and load_password().

2126 {
2127  char tmp[350];
2128  if (oldkey)
2129  snprintf(tmp, sizeof(tmp), "%s;%s", oldkey, newkey);
2130  else
2131  snprintf(tmp, sizeof(tmp), "%s", newkey);
2132  rotatetime = time(NULL) + DUNDI_SECRET_TIME;
2133  ast_db_put(secretpath, "secret", tmp);
2134  snprintf(tmp, sizeof(tmp), "%d", (int)rotatetime);
2135  ast_db_put(secretpath, "secretexpiry", tmp);
2136 }
static int tmp()
Definition: bt_open.c:389
#define NULL
Definition: resample.c:96
static char secretpath[80]
Definition: pbx_dundi.c:208
#define DUNDI_SECRET_TIME
Definition: pbx_dundi.c:181
static time_t rotatetime
Definition: pbx_dundi.c:211
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: main/db.c:327

◆ set_config()

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

Definition at line 4937 of file pbx_dundi.c.

References ast_category_browse(), ast_config_destroy(), ast_config_load, ast_copy_string(), ast_eid_default, ast_eid_is_empty(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log, ast_sockaddr_isnull(), ast_sockaddr_parse(), ast_sockaddr_set_port, ast_str2tos(), ast_str_to_eid(), ast_true(), ast_variable_browse(), build_mapping(), build_peer(), CONFIG_STATUS_FILEINVALID, DEFAULT_MAXMS, DUNDI_DEFAULT_CACHE_TIME, DUNDI_DEFAULT_TTL, DUNDI_MODEL_OUTBOUND, DUNDI_PORT, dundi_precache_full(), find_peer(), get_ipaddress(), ast_variable::lineno, load_password(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, mark_mappings(), mark_peers(), ast_variable::name, ast_variable::next, NULL, prune_mappings(), prune_peers(), set_host_ipaddr(), and ast_variable::value.

Referenced by load_module(), and reload().

4938 {
4939  struct ast_config *cfg;
4940  struct ast_variable *v;
4941  char *cat;
4942  int x;
4943  struct ast_flags config_flags = { 0 };
4944  static int last_port = 0;
4945  int port = 0;
4946  int globalpcmodel = 0;
4947  dundi_eid testeid;
4948  char bind_addr[80]={0,};
4949  char bind_addr2[80]={0,};
4950 
4951  if (!(cfg = ast_config_load(config_file, config_flags)) || cfg == CONFIG_STATUS_FILEINVALID) {
4952  ast_log(LOG_ERROR, "Unable to load config %s\n", config_file);
4953  return -1;
4954  }
4955 
4958  any_peer = NULL;
4959 
4960  AST_LIST_LOCK(&peers);
4961 
4963  ast_log(LOG_WARNING, "Entity ID is not set.\n");
4964  }
4965  memcpy(&global_eid, &ast_eid_default, sizeof(global_eid));
4966 
4967  global_storehistory = 0;
4968  ast_copy_string(secretpath, "dundi", sizeof(secretpath));
4969  v = ast_variable_browse(cfg, "general");
4970  while(v) {
4971  if (!strcasecmp(v->name, "port")){
4972  port = atoi(v->value);
4973  } else if (!strcasecmp(v->name, "bindaddr")) {
4974  if (get_ipaddress(bind_addr, sizeof(bind_addr), v->value, AF_UNSPEC) == 0) {
4975  if (!ast_sockaddr_parse(sin, bind_addr, 0)) {
4976  ast_log(LOG_WARNING, "Invalid host/IP '%s'\n", v->value);
4977  }
4978  }
4979  } else if (!strcasecmp(v->name, "bindaddr2")) {
4980  if (get_ipaddress(bind_addr2, sizeof(bind_addr2), v->value, AF_UNSPEC) == 0) {
4981  if (!ast_sockaddr_parse(sin2, bind_addr2, 0)) {
4982  ast_log(LOG_WARNING, "Invalid host/IP '%s'\n", v->value);
4983  }
4984  }
4985  } else if (!strcasecmp(v->name, "authdebug")) {
4986  authdebug = ast_true(v->value);
4987  } else if (!strcasecmp(v->name, "ttl")) {
4988  if ((sscanf(v->value, "%30d", &x) == 1) && (x > 0) && (x < DUNDI_DEFAULT_TTL)) {
4989  dundi_ttl = x;
4990  } else {
4991  ast_log(LOG_WARNING, "'%s' is not a valid TTL at line %d, must be number from 1 to %d\n",
4992  v->value, v->lineno, DUNDI_DEFAULT_TTL);
4993  }
4994  } else if (!strcasecmp(v->name, "autokill")) {
4995  if (sscanf(v->value, "%30d", &x) == 1) {
4996  if (x >= 0)
4998  else
4999  ast_log(LOG_NOTICE, "Nice try, but autokill has to be >0 or 'yes' or 'no' at line %d\n", v->lineno);
5000  } else if (ast_true(v->value)) {
5002  } else {
5004  }
5005  } else if (!strcasecmp(v->name, "entityid")) {
5006  if (!ast_str_to_eid(&testeid, v->value))
5007  global_eid = testeid;
5008  else
5009  ast_log(LOG_WARNING, "Invalid global endpoint identifier '%s' at line %d\n", v->value, v->lineno);
5010  } else if (!strcasecmp(v->name, "tos")) {
5011  if (ast_str2tos(v->value, &tos))
5012  ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno);
5013  } else if (!strcasecmp(v->name, "department")) {
5014  ast_copy_string(dept, v->value, sizeof(dept));
5015  } else if (!strcasecmp(v->name, "organization")) {
5016  ast_copy_string(org, v->value, sizeof(org));
5017  } else if (!strcasecmp(v->name, "locality")) {
5018  ast_copy_string(locality, v->value, sizeof(locality));
5019  } else if (!strcasecmp(v->name, "stateprov")) {
5020  ast_copy_string(stateprov, v->value, sizeof(stateprov));
5021  } else if (!strcasecmp(v->name, "country")) {
5022  ast_copy_string(country, v->value, sizeof(country));
5023  } else if (!strcasecmp(v->name, "email")) {
5024  ast_copy_string(email, v->value, sizeof(email));
5025  } else if (!strcasecmp(v->name, "phone")) {
5026  ast_copy_string(phone, v->value, sizeof(phone));
5027  } else if (!strcasecmp(v->name, "storehistory")) {
5029  } else if (!strcasecmp(v->name, "cachetime")) {
5030  if ((sscanf(v->value, "%30d", &x) == 1)) {
5031  dundi_cache_time = x;
5032  } else {
5033  ast_log(LOG_WARNING, "'%s' is not a valid cache time at line %d. Using default value '%d'.\n",
5035  }
5036  }
5037  v = v->next;
5038  }
5039 
5040  if (port == 0) {
5041  port = DUNDI_PORT;
5042  }
5043 
5044  if (ast_sockaddr_isnull(sin)) {
5045  sprintf(bind_addr, "0.0.0.0:%d", port);
5046  ast_sockaddr_parse(sin, bind_addr, 0);
5047  } else {
5048  ast_sockaddr_set_port(sin, port);
5049  }
5050 
5051  if (last_port == 0) {
5052  last_port = port;
5053  } else if (last_port != port) {
5054  ast_log(LOG_WARNING, "change to port ignored until next asterisk re-start\n");
5055  }
5056 
5057  set_host_ipaddr(sin);
5058 
5059  if (!ast_sockaddr_isnull(sin2)) {
5060  ast_sockaddr_set_port(sin2, port);
5061  }
5062 
5064 
5065  mark_mappings();
5066  v = ast_variable_browse(cfg, "mappings");
5067  while (v) {
5068  AST_LIST_LOCK(&peers);
5069  build_mapping(v->name, v->value);
5071  v = v->next;
5072  }
5073  prune_mappings();
5074 
5075  mark_peers();
5076  cat = ast_category_browse(cfg, NULL);
5077  while(cat) {
5078  if (strcasecmp(cat, "general") && strcasecmp(cat, "mappings")) {
5079  /* Entries */
5080  if (!ast_str_to_eid(&testeid, cat))
5081  build_peer(&testeid, ast_variable_browse(cfg, cat), &globalpcmodel);
5082  else if (!strcasecmp(cat, "*")) {
5083  build_peer(&empty_eid, ast_variable_browse(cfg, cat), &globalpcmodel);
5084  any_peer = find_peer(NULL);
5085  } else
5086  ast_log(LOG_NOTICE, "Ignoring invalid EID entry '%s'\n", cat);
5087  }
5088  cat = ast_category_browse(cfg, cat);
5089  }
5090  prune_peers();
5091 
5092  ast_config_destroy(cfg);
5093  load_password();
5094  if (globalpcmodel & DUNDI_MODEL_OUTBOUND)
5096  return 0;
5097 }
static void dundi_precache_full(void)
Definition: pbx_dundi.c:3972
struct ast_variable * next
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
static const char config_file[]
Definition: cdr_odbc.c:57
static void prune_mappings(void)
Definition: pbx_dundi.c:4427
static char locality[80]
Definition: pbx_dundi.c:203
static int get_ipaddress(char *ip, size_t size, const char *str, int family)
Definition: pbx_dundi.c:4901
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
static int dundi_cache_time
Definition: pbx_dundi.c:196
static dundi_eid global_eid
Definition: pbx_dundi.c:198
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1216
#define DUNDI_PORT
Definition: dundi.h:30
static void set_host_ipaddr(struct ast_sockaddr *sin)
Definition: pbx_dundi.c:4915
#define LOG_WARNING
Definition: logger.h:274
#define DUNDI_DEFAULT_CACHE_TIME
Definition: dundi.h:218
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define CONFIG_STATUS_FILEINVALID
static char email[80]
Definition: pbx_dundi.c:206
static char phone[80]
Definition: pbx_dundi.c:207
Structure for variables, used for configurations and for channel variables.
int ast_str2tos(const char *value, unsigned int *tos)
Convert a string to the appropriate TOS value.
Definition: acl.c:967
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3328
#define NULL
Definition: resample.c:96
static void load_password(void)
Definition: pbx_dundi.c:2138
An Entity ID is essentially a MAC address, brief and unique.
Definition: utils.h:786
static int authdebug
Definition: pbx_dundi.c:193
static char secretpath[80]
Definition: pbx_dundi.c:208
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_log
Definition: astobj2.c:42
#define ast_config_load(filename, flags)
Load a config file.
static struct dundi_peer * any_peer
Wildcard peer.
Definition: pbx_dundi.c:352
#define DUNDI_DEFAULT_TTL
Definition: dundi.h:216
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
static int global_storehistory
Definition: pbx_dundi.c:200
int ast_str_to_eid(struct ast_eid *eid, const char *s)
Convert a string into an EID.
Definition: main/utils.c:2825
static dundi_eid empty_eid
Definition: pbx_dundi.c:212
#define LOG_ERROR
Definition: logger.h:285
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
static struct dundi_peer * find_peer(dundi_eid *eid)
Definition: pbx_dundi.c:515
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:537
static char country[80]
Definition: pbx_dundi.c:205
static int global_autokilltimeout
Definition: pbx_dundi.c:197
#define LOG_NOTICE
Definition: logger.h:263
#define DEFAULT_MAXMS
Definition: chan_iax2.c:390
static unsigned int tos
Definition: pbx_dundi.c:191
static int dundi_ttl
Definition: pbx_dundi.c:194
Structure used to handle boolean flags.
Definition: utils.h:199
struct ast_eid ast_eid_default
Global EID.
Definition: options.c:93
static void mark_peers(void)
Definition: pbx_dundi.c:4353
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static void build_peer(dundi_eid *eid, struct ast_variable *v, int *globalpcmode)
Definition: pbx_dundi.c:4628
static char org[80]
Definition: pbx_dundi.c:202
static void mark_mappings(void)
Definition: pbx_dundi.c:4363
static void build_mapping(const char *name, const char *value)
Definition: pbx_dundi.c:4457
int ast_eid_is_empty(const struct ast_eid *eid)
Check if EID is empty.
Definition: main/utils.c:2847
#define DUNDI_MODEL_OUTBOUND
Definition: pbx_dundi.c:160
static void prune_peers(void)
Definition: pbx_dundi.c:4412
static char dept[80]
Definition: pbx_dundi.c:201
static char stateprov[80]
Definition: pbx_dundi.c:204

◆ set_host_ipaddr()

static void set_host_ipaddr ( struct ast_sockaddr sin)
static

Definition at line 4915 of file pbx_dundi.c.

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

Referenced by set_config().

4916 {
4917  char hn[MAXHOSTNAMELEN];
4918  struct addrinfo hints;
4919  int family;
4920 
4921  memset(&hints, 0, sizeof(hints));
4922 
4923  if (ast_sockaddr_is_ipv6(sin)) {
4924  family = AF_INET6;
4925  } else {
4926  family = AF_INET;
4927  }
4928 
4929  if (gethostname(hn, sizeof(hn) - 1) < 0) {
4930  ast_log(LOG_WARNING, "Unable to get host name!\n");
4931  return;
4932  }
4933 
4934  get_ipaddress(ipaddr, sizeof(ipaddr), hn, family);
4935 }
static int get_ipaddress(char *ip, size_t size, const char *str, int family)
Definition: pbx_dundi.c:4901
#define LOG_WARNING
Definition: logger.h:274
#define MAXHOSTNAMELEN
Definition: network.h:69
#define ast_log
Definition: astobj2.c:42
static char ipaddr[80]
Definition: pbx_dundi.c:210
int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
Determine if this is an IPv6 address.
Definition: netsock2.c:524

◆ socket_read()

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

Definition at line 2083 of file pbx_dundi.c.

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

Referenced by network_thread().

2084 {
2085  struct ast_sockaddr sin;
2086  int res;
2087  struct dundi_hdr *h;
2088  char buf[MAX_PACKET_SIZE];
2089 
2090  res = ast_recvfrom(*((int *)sock), buf, sizeof(buf), 0, &sin);
2091  if (res < 0) {
2092  if (errno != ECONNREFUSED)
2093  ast_log(LOG_WARNING, "Error: %s\n", strerror(errno));
2094  return 1;
2095  }
2096  if (res < sizeof(struct dundi_hdr)) {
2097  ast_log(LOG_WARNING, "midget packet received (%d of %d min)\n", res, (int)sizeof(struct dundi_hdr));
2098  return 1;
2099  }
2100  buf[res] = '\0';
2101  h = (struct dundi_hdr *) buf;
2102  if (dundidebug)
2103  dundi_showframe(h, 1, &sin, res - sizeof(struct dundi_hdr));
2104  AST_LIST_LOCK(&peers);
2105  handle_frame(h, &sin, res - sizeof(struct dundi_hdr));
2107  return 1;
2108 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define LOG_WARNING
Definition: logger.h:274
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
Socket address structure.
Definition: netsock2.h:97
#define ast_log
Definition: astobj2.c:42
static int dundidebug
Definition: pbx_dundi.c:192
int errno
ssize_t ast_recvfrom(int sockfd, void *buf, size_t len, int flags, struct ast_sockaddr *src_addr)
Wrapper around recvfrom(2) that uses struct ast_sockaddr.
Definition: netsock2.c:606
void dundi_showframe(struct dundi_hdr *fhi, int rx, struct ast_sockaddr *sin, int datalen)
Definition: dundi-parser.c:432
#define MAX_PACKET_SIZE
Definition: pbx_dundi.c:155
static int handle_frame(struct dundi_hdr *h, struct ast_sockaddr *sin, int datalen)
Definition: pbx_dundi.c:2042

◆ sort_results()

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

Definition at line 2451 of file pbx_dundi.c.

References rescomp().

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

2452 {
2453  qsort(results, count, sizeof(results[0]), rescomp);
2454 }
static int rescomp(const void *a, const void *b)
Definition: pbx_dundi.c:2439

◆ start_network_thread()

static int start_network_thread ( void  )
static

Definition at line 2296 of file pbx_dundi.c.

References ast_pthread_create_background, network_thread(), NULL, process_clearcache(), and process_precache().

Referenced by load_module().

2297 {
2301  return 0;
2302 }
static pthread_t precachethreadid
Definition: pbx_dundi.c:189
static void * process_precache(void *ign)
Definition: pbx_dundi.c:2261
static void * network_thread(void *ignore)
Definition: pbx_dundi.c:2194
#define NULL
Definition: resample.c:96
static pthread_t netthreadid
Definition: pbx_dundi.c:188
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:567
static pthread_t clearcachethreadid
Definition: pbx_dundi.c:190
static void * process_clearcache(void *ignore)
Definition: pbx_dundi.c:2228

◆ str2tech()

static int str2tech ( char *  str)
static

Definition at line 396 of file pbx_dundi.c.

References context, create_transaction(), dundi_lookup_internal(), dundi_precache_internal(), DUNDI_PROTO_H323, DUNDI_PROTO_IAX, DUNDI_PROTO_SIP, and result.

Referenced by build_mapping().

397 {
398  if (!strcasecmp(str, "IAX") || !strcasecmp(str, "IAX2"))
399  return DUNDI_PROTO_IAX;
400  else if (!strcasecmp(str, "SIP"))
401  return DUNDI_PROTO_SIP;
402  else if (!strcasecmp(str, "H323"))
403  return DUNDI_PROTO_H323;
404  else
405  return -1;
406 }
const char * str
Definition: app_jack.c:147

◆ tech2str()

static char* tech2str ( int  tech)
static

Definition at line 380 of file pbx_dundi.c.

References DUNDI_PROTO_H323, DUNDI_PROTO_IAX, DUNDI_PROTO_NONE, and DUNDI_PROTO_SIP.

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

381 {
382  switch(tech) {
383  case DUNDI_PROTO_NONE:
384  return "None";
385  case DUNDI_PROTO_IAX:
386  return "IAX2";
387  case DUNDI_PROTO_SIP:
388  return "SIP";
389  case DUNDI_PROTO_H323:
390  return "H323";
391  default:
392  return "Unknown";
393  }
394 }

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 5099 of file pbx_dundi.c.

References ARRAY_LEN, ast_cli_unregister_multiple(), ast_custom_function_unregister(), AST_PTHREADT_NULL, ast_sched_context_destroy(), ast_unregister_switch(), io_context_destroy(), mark_mappings(), mark_peers(), NULL, prune_mappings(), and prune_peers().

Referenced by load_module().

5100 {
5106 
5107  /* Stop all currently running threads */
5108  dundi_shutdown = 1;
5109  if (netthreadid != AST_PTHREADT_NULL) {
5110  pthread_kill(netthreadid, SIGURG);
5111  pthread_join(netthreadid, NULL);
5113  }
5115  pthread_kill(precachethreadid, SIGURG);
5116  pthread_join(precachethreadid, NULL);
5118  }
5120  pthread_cancel(clearcachethreadid);
5121  pthread_join(clearcachethreadid, NULL);
5123  }
5124 
5125  if (netsocket >= 0) {
5126  close(netsocket);
5127  }
5128 
5129  if (netsocket2 >= 0) {
5130  close(netsocket2);
5131  }
5132 
5133  mark_mappings();
5134  prune_mappings();
5135  mark_peers();
5136  prune_peers();
5137 
5138  if (-1 < netsocket) {
5139  close(netsocket);
5140  netsocket = -1;
5141  }
5142  if (io) {
5144  io = NULL;
5145  }
5146 
5147  if (sched) {
5149  sched = NULL;
5150  }
5151 
5152  return 0;
5153 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static void prune_mappings(void)
Definition: pbx_dundi.c:4427
static pthread_t precachethreadid
Definition: pbx_dundi.c:189
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
static struct io_context * io
Definition: pbx_dundi.c:184
Definition: sched.c:76
void ast_unregister_switch(struct ast_switch *sw)
Unregister an alternative switch.
Definition: pbx_switch.c:76
#define NULL
Definition: resample.c:96
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
static pthread_t netthreadid
Definition: pbx_dundi.c:188
static int netsocket
Definition: pbx_dundi.c:186
void io_context_destroy(struct io_context *ioc)
Destroys a context.
Definition: io.c:107
#define AST_PTHREADT_NULL
Definition: lock.h:66
static struct ast_custom_function dundi_function
Definition: pbx_dundi.c:4186
static pthread_t clearcachethreadid
Definition: pbx_dundi.c:190
static struct ast_cli_entry cli_dundi[]
Definition: pbx_dundi.c:3119
static int dundi_shutdown
Definition: pbx_dundi.c:213
static void mark_peers(void)
Definition: pbx_dundi.c:4353
static void mark_mappings(void)
Definition: pbx_dundi.c:4363
static struct ast_custom_function dundi_query_function
Definition: pbx_dundi.c:4274
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
Definition: sched.c:269
static struct ast_switch dundi_switch
Definition: pbx_dundi.c:4892
static int netsocket2
Definition: pbx_dundi.c:187
static void prune_peers(void)
Definition: pbx_dundi.c:4412
static struct ast_custom_function dundi_result_function
Definition: pbx_dundi.c:4348

◆ unregister_request()

static void unregister_request ( struct dundi_request dr)
static

Definition at line 3788 of file pbx_dundi.c.

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

Referenced by dundi_lookup_internal().

3789 {
3790  AST_LIST_LOCK(&peers);
3791  AST_LIST_REMOVE(&requests, dr, list);
3793 }
#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_REMOVE(head, elm, field)
Removes a specific entry from a list.
Definition: linkedlists.h:855

◆ update_key()

static int update_key ( struct dundi_peer peer)
static

Definition at line 1334 of file pbx_dundi.c.

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

Referenced by dundi_encrypt().

1335 {
1336  unsigned char key[16];
1337  struct ast_key *ekey, *skey;
1338  char eid_str[20];
1339  int res;
1340  if (!peer->keyexpire || (peer->keyexpire < time(NULL))) {
1341  build_iv(key);
1342  ast_aes_set_encrypt_key(key, &peer->us_ecx);
1343  ast_aes_set_decrypt_key(key, &peer->us_dcx);
1344  ekey = ast_key_get(peer->inkey, AST_KEY_PUBLIC);
1345  if (!ekey) {
1346  ast_log(LOG_NOTICE, "No such key '%s' for creating RSA encrypted shared key for '%s'!\n",
1347  peer->inkey, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
1348  return -1;
1349  }
1350  skey = ast_key_get(peer->outkey, AST_KEY_PRIVATE);
1351  if (!skey) {
1352  ast_log(LOG_NOTICE, "No such key '%s' for signing RSA encrypted shared key for '%s'!\n",
1353  peer->outkey, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
1354  return -1;
1355  }
1356  if ((res = ast_encrypt_bin(peer->txenckey, key, sizeof(key), ekey)) != 128) {
1357  ast_log(LOG_NOTICE, "Whoa, got a weird encrypt size (%d != %d)!\n", res, 128);
1358  return -1;
1359  }
1360  if ((res = ast_sign_bin(skey, (char *)peer->txenckey, 128, peer->txenckey + 128))) {
1361  ast_log(LOG_NOTICE, "Failed to sign key (%d)!\n", res);
1362  return -1;
1363  }
1364  peer->us_keycrc32 = crc32(0L, peer->txenckey, 128);
1365  peer->sentfullkey = 0;
1366  /* Looks good */
1367  time(&peer->keyexpire);
1368  peer->keyexpire += dundi_key_ttl;
1369  }
1370  return 0;
1371 }
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 dundi_key_ttl
Definition: pbx_dundi.c:195
char outkey[80]
Definition: pbx_dundi.c:310
#define NULL
Definition: resample.c:96
time_t keyexpire
Definition: pbx_dundi.c:324
uint32_t us_keycrc32
Definition: pbx_dundi.c:318
#define ast_log
Definition: astobj2.c:42
ast_aes_decrypt_key us_dcx
Definition: pbx_dundi.c:320
static void build_iv(unsigned char *iv)
Definition: pbx_dundi.c:533
#define AST_KEY_PRIVATE
Definition: crypto.h:43
int AST_OPTIONAL_API_NAME() ast_encrypt_bin(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key)
encrypt a message
Definition: res_crypto.c:368
#define LOG_NOTICE
Definition: logger.h:263
int AST_OPTIONAL_API_NAME() ast_sign_bin(struct ast_key *key, const char *msg, int msglen, unsigned char *dsig)
signs outgoing message with public key
Definition: res_crypto.c:304
dundi_eid eid
Definition: pbx_dundi.c:304
char inkey[80]
Definition: pbx_dundi.c:309
ast_aes_encrypt_key us_ecx
Definition: pbx_dundi.c:319
unsigned char txenckey[256]
Definition: pbx_dundi.c:316
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 sentfullkey
Definition: pbx_dundi.c:314

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Distributed Universal Number Discovery (DUNDi)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .optional_modules = "res_crypto", }
static

Definition at line 5278 of file pbx_dundi.c.

◆ alltrans

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

◆ any_peer

struct dundi_peer* any_peer
static

Wildcard peer.

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

Definition at line 352 of file pbx_dundi.c.

Referenced by find_peer().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 5278 of file pbx_dundi.c.

◆ authdebug

int authdebug = 0
static

Definition at line 193 of file pbx_dundi.c.

◆ clearcachethreadid

pthread_t clearcachethreadid = AST_PTHREADT_NULL
static

Definition at line 190 of file pbx_dundi.c.

◆ cli_dundi

struct ast_cli_entry cli_dundi[]
static

Definition at line 3119 of file pbx_dundi.c.

◆ country

char country[80]
static

Definition at line 205 of file pbx_dundi.c.

Referenced by ast_var_channels_table(), func_channel_read(), and load_indications().

◆ cursecret

char cursecret[80]
static

Definition at line 209 of file pbx_dundi.c.

◆ default_expiration

int default_expiration = 60
static

Definition at line 199 of file pbx_dundi.c.

Referenced by ast_sip_initialize_sorcery_location(), and handle_command_response().

◆ dept

char dept[80]
static

Definition at line 201 of file pbx_dundi.c.

◆ dundi_cache_time

int dundi_cache_time = DUNDI_DEFAULT_CACHE_TIME
static

◆ dundi_key_ttl

int dundi_key_ttl = DUNDI_DEFAULT_KEY_EXPIRE
static

Definition at line 195 of file pbx_dundi.c.

Referenced by update_key().

◆ dundi_query_function

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

Definition at line 4274 of file pbx_dundi.c.

◆ dundi_query_opts

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

Definition at line 4135 of file pbx_dundi.c.

Referenced by dundi_query_read(), and dundifunc_read().

◆ dundi_result_datastore_info

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

Definition at line 4210 of file pbx_dundi.c.

◆ dundi_result_function

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

Definition at line 4348 of file pbx_dundi.c.

◆ dundi_result_id

unsigned int dundi_result_id
static

Definition at line 4191 of file pbx_dundi.c.

◆ dundi_shutdown

int dundi_shutdown = 0
static

Definition at line 213 of file pbx_dundi.c.

◆ dundi_switch

struct ast_switch dundi_switch
static

Definition at line 4892 of file pbx_dundi.c.

◆ dundi_ttl

int dundi_ttl = DUNDI_DEFAULT_TTL
static

Definition at line 194 of file pbx_dundi.c.

◆ dundidebug

int dundidebug = 0
static

Definition at line 192 of file pbx_dundi.c.

◆ email

char email[80]
static

Definition at line 206 of file pbx_dundi.c.

Referenced by make_email_file().

◆ empty_eid

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

Definition at line 212 of file pbx_dundi.c.

Referenced by find_peer().

◆ global_autokilltimeout

int global_autokilltimeout = 0
static

Definition at line 197 of file pbx_dundi.c.

Referenced by apply_peer().

◆ global_eid

dundi_eid global_eid
static

Definition at line 198 of file pbx_dundi.c.

Referenced by build_peer().

◆ global_storehistory

int global_storehistory = 0
static

Definition at line 200 of file pbx_dundi.c.

◆ io

struct io_context* io
static

Definition at line 184 of file pbx_dundi.c.

◆ ipaddr

char ipaddr[80]
static

Definition at line 210 of file pbx_dundi.c.

Referenced by realtime_peer(), and realtime_update_peer().

◆ locality

char locality[80]
static

Definition at line 203 of file pbx_dundi.c.

◆ mappings

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

◆ netsocket

int netsocket = -1
static

Definition at line 186 of file pbx_dundi.c.

Referenced by ast_netsock_bindaddr(), and handle_error().

◆ netsocket2

int netsocket2 = -1
static

Definition at line 187 of file pbx_dundi.c.

◆ netthreadid

pthread_t netthreadid = AST_PTHREADT_NULL
static

Definition at line 188 of file pbx_dundi.c.

◆ org

char org[80]
static

Definition at line 202 of file pbx_dundi.c.

Referenced by calc_crc().

◆ pcq

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

◆ peers

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

◆ phone

char phone[80]
static

Definition at line 207 of file pbx_dundi.c.

Referenced by privacy_exec().

◆ precachethreadid

pthread_t precachethreadid = AST_PTHREADT_NULL
static

Definition at line 189 of file pbx_dundi.c.

◆ requests

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

Referenced by ast_aoc_create().

◆ rotatetime

time_t rotatetime
static

Definition at line 211 of file pbx_dundi.c.

◆ sched

struct ast_sched_context* sched
static

Definition at line 185 of file pbx_dundi.c.

◆ secretpath

char secretpath[80]
static

Definition at line 208 of file pbx_dundi.c.

◆ stateprov

char stateprov[80]
static

Definition at line 204 of file pbx_dundi.c.

◆ tos

unsigned int tos = 0
static

Definition at line 191 of file pbx_dundi.c.