Wed Jan 8 2020 09:50:16

Asterisk developer's documentation


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 <sys/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/netsock.h"
#include "asterisk/crypto.h"
#include "asterisk/astdb.h"
#include "asterisk/acl.h"
#include "asterisk/app.h"
#include "dundi-parser.h"

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 %-15.15s %s %-6d %-10.10s %-8.8s %-15.15s\n"
 
#define FORMAT   "%-16.16s:%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 FORMAT2   "%-20.20s %-15.15s %-6.6s %-10.10s %-8.8s %-15.15s\n"
 
#define FORMAT2   "%-22.22s %-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 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)
 
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 crc32, 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 sockaddr_in *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_entityid (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 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 sockaddr_in *sin)
 
static int get_mapping_weight (struct dundi_mapping *map)
 
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 sockaddr_in *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 sockaddr_in *sin, int reload)
 
static int socket_read (int *id, int fd, short events, void *cbdata)
 
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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, .nonoptreq = "res_crypto", }
 
static struct alltrans alltrans = { .first = NULL, .last = NULL, }
 
static struct dundi_peerany_peer
 Wildcard peer. More...
 
static 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 struct ast_app_option dundi_query_opts [128] = { [ 'b' ] = { .flag = OPT_BYPASS_CACHE }, }
 
static 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 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 } , }
 
static struct peers peers = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } , }
 
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 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

#define DUNDI_FLAG_INTERNAL_NOPARTIAL   (1 << 17)

Definition at line 168 of file pbx_dundi.c.

Referenced by build_mapping(), and dundi_lookup_local().

#define DUNDI_MODEL_INBOUND   (1 << 0)

Definition at line 151 of file pbx_dundi.c.

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

#define DUNDI_MODEL_OUTBOUND   (1 << 1)

Definition at line 152 of file pbx_dundi.c.

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

#define DUNDI_MODEL_SYMMETRIC   (DUNDI_MODEL_INBOUND | DUNDI_MODEL_OUTBOUND)

Definition at line 153 of file pbx_dundi.c.

Referenced by build_peer(), and model2str().

#define DUNDI_SECRET_TIME   DUNDI_DEFAULT_CACHE_TIME

Definition at line 173 of file pbx_dundi.c.

Referenced by load_password(), and save_secret().

#define DUNDI_TIMING_HISTORY   10

Keep times of last 10 lookups

Definition at line 156 of file pbx_dundi.c.

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

#define FORMAT   "%-20.20s %-15.15s %s %-6d %-10.10s %-8.8s %-15.15s\n"
#define FORMAT   "%-16.16s:%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 FORMAT2   "%-20.20s %-15.15s %-6.6s %-10.10s %-8.8s %-15.15s\n"
#define FORMAT2   "%-22.22s %-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 MAX_OPTS   128

Definition at line 4196 of file pbx_dundi.c.

Referenced by build_mapping().

#define MAX_PACKET_SIZE   8192

Definition at line 147 of file pbx_dundi.c.

Referenced by handle_command_response(), and socket_read().

#define MAX_RESULTS   64

Definition at line 145 of file pbx_dundi.c.

Referenced by dundi_precache_internal(), and dundi_prop_precache().

#define MAX_WEIGHT   59999

Definition at line 149 of file pbx_dundi.c.

Referenced by build_mapping(), and get_mapping_weight().

Enumeration Type Documentation

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

158  {
159  FLAG_ISREG = (1 << 0), /*!< Transaction is register request */
160  FLAG_DEAD = (1 << 1), /*!< Transaction is dead */
161  FLAG_FINAL = (1 << 2), /*!< Transaction has final message sent */
162  FLAG_ISQUAL = (1 << 3), /*!< Transaction is a qualification */
163  FLAG_ENCRYPT = (1 << 4), /*!< Transaction is encrypted wiht ECX/DCX */
164  FLAG_SENDFULLKEY = (1 << 5), /*!< Send full key on transaction */
165  FLAG_STOREHIST = (1 << 6), /*!< Record historic performance */
166 };
anonymous enum
Enumerator
OPT_BYPASS_CACHE 

Definition at line 3882 of file pbx_dundi.c.

3882  {
3883  OPT_BYPASS_CACHE = (1 << 0),
3884 };

Function Documentation

static void __reg_module ( void  )
static

Definition at line 4867 of file pbx_dundi.c.

static void __unreg_module ( void  )
static

Definition at line 4867 of file pbx_dundi.c.

static void abort_request ( struct dundi_request dr)
static

Definition at line 3440 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().

3441 {
3442  struct dundi_transaction *trans;
3443 
3444  AST_LIST_LOCK(&peers);
3445  while ((trans = AST_LIST_FIRST(&dr->trans))) {
3446  /* This will remove the transaction from the list */
3447  destroy_trans(trans, 0);
3448  }
3450 }
#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:2956
struct dundi_request::@315 trans
static int ack_trans ( struct dundi_transaction trans,
int  iseqno 
)
static

Definition at line 1989 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, LOG_WARNING, dundi_hdr::oseqno, and dundi_transaction::packets.

Referenced by handle_frame().

1990 {
1991  struct dundi_packet *pack;
1992 
1993  /* Ack transmitted packet corresponding to iseqno */
1994  AST_LIST_TRAVERSE(&trans->packets, pack, list) {
1995  if ((pack->h->oseqno + 1) % 255 == iseqno) {
1996  destroy_packet(pack, 0);
1997  if (!AST_LIST_EMPTY(&trans->lasttrans)) {
1998  ast_log(LOG_WARNING, "Whoa, there was still a last trans?\n");
1999  destroy_packets(&trans->lasttrans);
2000  }
2001  AST_LIST_INSERT_HEAD(&trans->lasttrans, pack, list);
2002  AST_SCHED_DEL(sched, trans->autokillid);
2003  return 1;
2004  }
2005  }
2006 
2007  return 0;
2008 }
#define LOG_WARNING
Definition: logger.h:144
Definition: sched.c:57
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
struct packetlist lasttrans
Definition: pbx_dundi.c:258
unsigned char oseqno
Definition: dundi.h:38
#define AST_SCHED_DEL(sched, id)
a loop construct to ensure that the scheduled task get deleted. The idea is that if we loop attemptin...
Definition: sched.h:51
struct dundi_transaction::packetlist packets
static void destroy_packet(struct dundi_packet *pack, int needfree)
Definition: pbx_dundi.c:2947
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#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:696
static void destroy_packets(struct packetlist *p)
Definition: pbx_dundi.c:1978
struct dundi_packet::@311 list
struct dundi_hdr * h
Definition: pbx_dundi.c:214
static void append_permission ( struct permissionlist *  permlist,
const char *  s,
int  allow 
)
static

Definition at line 4183 of file pbx_dundi.c.

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

Referenced by build_peer().

4184 {
4185  struct permission *perm;
4186 
4187  if (!(perm = ast_calloc(1, sizeof(*perm) + strlen(s) + 1)))
4188  return;
4189 
4190  strcpy(perm->name, s);
4191  perm->allow = allow;
4192 
4193  AST_LIST_INSERT_TAIL(permlist, perm, list);
4194 }
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
char name[0]
Definition: pbx_dundi.c:209
#define ast_calloc(a, b)
Definition: astmm.h:82
struct permission::@310 list
static int append_transaction ( struct dundi_request dr,
struct dundi_peer p,
int  ttl,
dundi_eid avoid[] 
)
static

Definition at line 3395 of file pbx_dundi.c.

References dundi_peer::addr, ast_debug, ast_eid_to_str(), AST_LIST_INSERT_HEAD, 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_request::query_eid, dundi_request::trans, and dundi_transaction::ttl.

Referenced by build_transactions().

3396 {
3397  struct dundi_transaction *trans;
3398  int x;
3399  char eid_str[20];
3400  char eid_str2[20];
3401 
3402  /* Ignore if not registered */
3403  if (!p->addr.sin_addr.s_addr)
3404  return 0;
3405  if (p->maxms && ((p->lastms < 0) || (p->lastms >= p->maxms)))
3406  return 0;
3407 
3408  if (ast_strlen_zero(dr->number))
3409  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);
3410  else
3411  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);
3412 
3413  trans = create_transaction(p);
3414  if (!trans)
3415  return -1;
3416  trans->parent = dr;
3417  trans->ttl = ttl;
3418  for (x = 0; avoid[x] && (x < DUNDI_MAX_STACK); x++)
3419  trans->eids[x] = *avoid[x];
3420  trans->eidcount = x;
3421  AST_LIST_INSERT_HEAD(&dr->trans, trans, parentlist);
3422 
3423  return 0;
3424 }
static float dr[4]
Definition: tdd.c:59
struct sockaddr_in addr
Definition: pbx_dundi.c:296
struct dundi_request * parent
Definition: pbx_dundi.c:259
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Definition: netsock.c:222
dundi_eid eids[DUNDI_MAX_STACK+1]
Definition: pbx_dundi.c:239
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:265
int lastms
Definition: pbx_dundi.c:326
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static struct dundi_transaction * create_transaction(struct dundi_peer *p)
Definition: pbx_dundi.c:2900
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
dundi_eid query_eid
Definition: pbx_dundi.c:267
char number[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:266
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:696
dundi_eid eid
Definition: pbx_dundi.c:295
#define DUNDI_MAX_STACK
Definition: dundi-parser.h:18
struct dundi_request::@315 trans
struct dundi_transaction::@313 parentlist
static void apply_peer ( struct dundi_transaction trans,
struct dundi_peer p 
)
static

Definition at line 1276 of file pbx_dundi.c.

References dundi_transaction::addr, dundi_peer::addr, ast_set_flag, 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().

1277 {
1278  if (!trans->addr.sin_addr.s_addr)
1279  memcpy(&trans->addr, &p->addr, sizeof(trans->addr));
1280  trans->us_eid = p->us_eid;
1281  trans->them_eid = p->eid;
1282  /* Enable encryption if appropriate */
1283  if (!ast_strlen_zero(p->inkey))
1284  ast_set_flag(trans, FLAG_ENCRYPT);
1285  if (p->maxms) {
1286  trans->autokilltimeout = p->maxms;
1288  if (p->lastms > 1) {
1289  trans->retranstimer = p->lastms * 2;
1290  /* Keep it from being silly */
1291  if (trans->retranstimer < 150)
1292  trans->retranstimer = 150;
1293  }
1296  } else
1298 }
struct sockaddr_in addr
Definition: pbx_dundi.c:296
#define ast_set_flag(p, flag)
Definition: utils.h:70
dundi_eid us_eid
Definition: pbx_dundi.c:241
dundi_eid them_eid
Definition: pbx_dundi.c:242
int lastms
Definition: pbx_dundi.c:326
#define DUNDI_DEFAULT_RETRANS_TIMER
Definition: dundi.h:215
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
dundi_eid us_eid
Definition: pbx_dundi.c:299
static int global_autokilltimeout
Definition: pbx_dundi.c:188
dundi_eid eid
Definition: pbx_dundi.c:295
struct sockaddr_in addr
Definition: pbx_dundi.c:237
char inkey[80]
Definition: pbx_dundi.c:300
static unsigned long avoid_crc32 ( dundi_eid avoid[])
static

Definition at line 3561 of file pbx_dundi.c.

References dundi_request::crc32.

Referenced by dundi_lookup_internal().

3562 {
3563  /* Idea is that we're calculating a checksum which is independent of
3564  the order that the EID's are listed in */
3565  uint32_t acrc32 = 0;
3566  int x;
3567  for (x=0;avoid[x];x++) {
3568  /* Order doesn't matter */
3569  if (avoid[x+1]) {
3570  acrc32 ^= crc32(0L, (unsigned char *)avoid[x], sizeof(dundi_eid));
3571  }
3572  }
3573  return acrc32;
3574 }
An Entity ID is essentially a MAC address, brief and unique.
Definition: utils.h:808
static void build_iv ( unsigned char *  iv)
static

Definition at line 522 of file pbx_dundi.c.

References ast_random().

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

523 {
524  /* XXX Would be nice to be more random XXX */
525  unsigned int *fluffy;
526  int x;
527  fluffy = (unsigned int *)(iv);
528  for (x=0;x<4;x++)
529  fluffy[x] = ast_random();
530 }
long int ast_random(void)
Definition: utils.c:1640
static void build_mapping ( const char *  name,
const char *  value 
)
static

Definition at line 4198 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, LOG_WARNING, map, MAX_OPTS, MAX_WEIGHT, dundi_mapping::options, str2tech(), dundi_mapping::tech, and dundi_mapping::weightstr.

Referenced by set_config().

4199 {
4200  char *t, *fields[MAX_OPTS];
4201  struct dundi_mapping *map;
4202  int x;
4203  int y;
4204 
4205  t = ast_strdupa(value);
4206 
4207  AST_LIST_TRAVERSE(&mappings, map, list) {
4208  /* Find a double match */
4209  if (!strcasecmp(map->dcontext, name) &&
4210  (!strncasecmp(map->lcontext, value, strlen(map->lcontext)) &&
4211  (!value[strlen(map->lcontext)] ||
4212  (value[strlen(map->lcontext)] == ','))))
4213  break;
4214  }
4215  if (!map) {
4216  if (!(map = ast_calloc(1, sizeof(*map))))
4217  return;
4219  map->dead = 1;
4220  }
4221  map->options = 0;
4222  memset(fields, 0, sizeof(fields));
4223  x = 0;
4224  while (t && x < MAX_OPTS) {
4225  fields[x++] = t;
4226  t = strchr(t, ',');
4227  if (t) {
4228  *t = '\0';
4229  t++;
4230  }
4231  } /* Russell was here, arrrr! */
4232  if ((x == 1) && ast_strlen_zero(fields[0])) {
4233  /* Placeholder mapping */
4234  ast_copy_string(map->dcontext, name, sizeof(map->dcontext));
4235  map->dead = 0;
4236  } else if (x >= 4) {
4237  ast_copy_string(map->dcontext, name, sizeof(map->dcontext));
4238  ast_copy_string(map->lcontext, fields[0], sizeof(map->lcontext));
4239  if ((sscanf(fields[1], "%30d", &map->_weight) == 1) && (map->_weight >= 0) && (map->_weight <= MAX_WEIGHT)) {
4240  ast_copy_string(map->dest, fields[3], sizeof(map->dest));
4241  if ((map->tech = str2tech(fields[2])))
4242  map->dead = 0;
4243  } else if (!strncmp(fields[1], "${", 2) && fields[1][strlen(fields[1]) - 1] == '}') {
4244  map->weightstr = ast_strdup(fields[1]);
4245  ast_copy_string(map->dest, fields[3], sizeof(map->dest));
4246  if ((map->tech = str2tech(fields[2])))
4247  map->dead = 0;
4248  } else {
4249  ast_log(LOG_WARNING, "Invalid weight '%s' specified, deleting entry '%s/%s'\n", fields[1], map->dcontext, map->lcontext);
4250  }
4251  for (y = 4;y < x; y++) {
4252  if (!strcasecmp(fields[y], "nounsolicited"))
4254  else if (!strcasecmp(fields[y], "nocomunsolicit"))
4256  else if (!strcasecmp(fields[y], "residential"))
4258  else if (!strcasecmp(fields[y], "commercial"))
4260  else if (!strcasecmp(fields[y], "mobile"))
4261  map->options |= DUNDI_FLAG_MOBILE;
4262  else if (!strcasecmp(fields[y], "nopartial"))
4264  else
4265  ast_log(LOG_WARNING, "Don't know anything about option '%s'\n", fields[y]);
4266  }
4267  } else
4268  ast_log(LOG_WARNING, "Expected at least %d arguments in map, but got only %d\n", 4, x);
4269 }
struct dundi_mapping::@317 list
char dest[512]
Definition: pbx_dundi.c:290
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:283
#define ast_strdup(a)
Definition: astmm.h:109
char lcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:284
static int * map
Definition: misdn_config.c:434
#define LOG_WARNING
Definition: logger.h:144
int value
Definition: syslog.c:39
#define DUNDI_FLAG_INTERNAL_NOPARTIAL
Definition: pbx_dundi.c:168
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#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:696
static const char name[]
char * weightstr
Definition: pbx_dundi.c:286
#define ast_calloc(a, b)
Definition: astmm.h:82
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static int str2tech(char *str)
Definition: pbx_dundi.c:387
#define MAX_OPTS
Definition: pbx_dundi.c:4196
#define MAX_WEIGHT
Definition: pbx_dundi.c:149
static void build_peer ( dundi_eid eid,
struct ast_variable v,
int *  globalpcmode 
)
static

Definition at line 4353 of file pbx_dundi.c.

References dundi_peer::addr, append_permission(), ast_calloc, ast_copy_string(), ast_eid_cmp(), ast_eid_to_str(), ast_gethostbyname(), 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_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, hp, dundi_peer::include, dundi_peer::inkey, ast_variable::lineno, LOG_WARNING, dundi_peer::maxms, dundi_peer::model, ast_variable::name, ast_variable::next, dundi_peer::order, dundi_peer::outkey, 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().

4354 {
4355  struct dundi_peer *peer;
4356  struct ast_hostent he;
4357  struct hostent *hp;
4358  dundi_eid testeid;
4359  int needregister=0;
4360  char eid_str[20];
4361 
4362  AST_LIST_LOCK(&peers);
4363  AST_LIST_TRAVERSE(&peers, peer, list) {
4364  if (!ast_eid_cmp(&peer->eid, eid)) {
4365  break;
4366  }
4367  }
4368  if (!peer) {
4369  /* Add us into the list */
4370  if (!(peer = ast_calloc(1, sizeof(*peer)))) {
4372  return;
4373  }
4374  peer->registerid = -1;
4375  peer->registerexpire = -1;
4376  peer->qualifyid = -1;
4377  peer->addr.sin_family = AF_INET;
4378  peer->addr.sin_port = htons(DUNDI_PORT);
4379  populate_addr(peer, eid);
4380  AST_LIST_INSERT_HEAD(&peers, peer, list);
4381  }
4382  peer->dead = 0;
4383  peer->eid = *eid;
4384  peer->us_eid = global_eid;
4385  destroy_permissions(&peer->permit);
4386  destroy_permissions(&peer->include);
4387  AST_SCHED_DEL(sched, peer->registerid);
4388  for (; v; v = v->next) {
4389  if (!strcasecmp(v->name, "inkey")) {
4390  ast_copy_string(peer->inkey, v->value, sizeof(peer->inkey));
4391  } else if (!strcasecmp(v->name, "outkey")) {
4392  ast_copy_string(peer->outkey, v->value, sizeof(peer->outkey));
4393  } else if (!strcasecmp(v->name, "port")) {
4394  peer->addr.sin_port = htons(atoi(v->value));
4395  } else if (!strcasecmp(v->name, "host")) {
4396  if (!strcasecmp(v->value, "dynamic")) {
4397  peer->dynamic = 1;
4398  } else {
4399  hp = ast_gethostbyname(v->value, &he);
4400  if (hp) {
4401  memcpy(&peer->addr.sin_addr, hp->h_addr, sizeof(peer->addr.sin_addr));
4402  peer->dynamic = 0;
4403  } else {
4404  ast_log(LOG_WARNING, "Unable to find host '%s' at line %d\n", v->value, v->lineno);
4405  peer->dead = 1;
4406  }
4407  }
4408  } else if (!strcasecmp(v->name, "ustothem")) {
4409  if (!ast_str_to_eid(&testeid, v->value))
4410  peer->us_eid = testeid;
4411  else
4412  ast_log(LOG_WARNING, "'%s' is not a valid DUNDi Entity Identifier at line %d\n", v->value, v->lineno);
4413  } else if (!strcasecmp(v->name, "include")) {
4414  append_permission(&peer->include, v->value, 1);
4415  } else if (!strcasecmp(v->name, "permit")) {
4416  append_permission(&peer->permit, v->value, 1);
4417  } else if (!strcasecmp(v->name, "noinclude")) {
4418  append_permission(&peer->include, v->value, 0);
4419  } else if (!strcasecmp(v->name, "deny")) {
4420  append_permission(&peer->permit, v->value, 0);
4421  } else if (!strcasecmp(v->name, "register")) {
4422  needregister = ast_true(v->value);
4423  } else if (!strcasecmp(v->name, "order")) {
4424  if (!strcasecmp(v->value, "primary"))
4425  peer->order = 0;
4426  else if (!strcasecmp(v->value, "secondary"))
4427  peer->order = 1;
4428  else if (!strcasecmp(v->value, "tertiary"))
4429  peer->order = 2;
4430  else if (!strcasecmp(v->value, "quartiary"))
4431  peer->order = 3;
4432  else {
4433  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);
4434  }
4435  } else if (!strcasecmp(v->name, "qualify")) {
4436  if (!strcasecmp(v->value, "no")) {
4437  peer->maxms = 0;
4438  } else if (!strcasecmp(v->value, "yes")) {
4439  peer->maxms = DEFAULT_MAXMS;
4440  } else if (sscanf(v->value, "%30d", &peer->maxms) != 1) {
4441  ast_log(LOG_WARNING, "Qualification of peer '%s' should be 'yes', 'no', or a number of milliseconds at line %d of dundi.conf\n",
4442  ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), v->lineno);
4443  peer->maxms = 0;
4444  }
4445  } else if (!strcasecmp(v->name, "model")) {
4446  if (!strcasecmp(v->value, "inbound"))
4447  peer->model = DUNDI_MODEL_INBOUND;
4448  else if (!strcasecmp(v->value, "outbound"))
4449  peer->model = DUNDI_MODEL_OUTBOUND;
4450  else if (!strcasecmp(v->value, "symmetric"))
4451  peer->model = DUNDI_MODEL_SYMMETRIC;
4452  else if (!strcasecmp(v->value, "none"))
4453  peer->model = 0;
4454  else {
4455  ast_log(LOG_WARNING, "Unknown model '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n",
4456  v->value, v->lineno);
4457  }
4458  } else if (!strcasecmp(v->name, "precache")) {
4459  if (!strcasecmp(v->value, "inbound"))
4460  peer->pcmodel = DUNDI_MODEL_INBOUND;
4461  else if (!strcasecmp(v->value, "outbound"))
4462  peer->pcmodel = DUNDI_MODEL_OUTBOUND;
4463  else if (!strcasecmp(v->value, "symmetric"))
4465  else if (!strcasecmp(v->value, "none"))
4466  peer->pcmodel = 0;
4467  else {
4468  ast_log(LOG_WARNING, "Unknown pcmodel '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n",
4469  v->value, v->lineno);
4470  }
4471  }
4472  }
4473  (*globalpcmode) |= peer->pcmodel;
4474  if (!peer->model && !peer->pcmodel) {
4475  ast_log(LOG_WARNING, "Peer '%s' lacks a model or pcmodel, discarding!\n",
4476  ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
4477  peer->dead = 1;
4478  } else if ((peer->model & DUNDI_MODEL_INBOUND) && (peer->pcmodel & DUNDI_MODEL_OUTBOUND)) {
4479  ast_log(LOG_WARNING, "Peer '%s' may not be both inbound/symmetric model and outbound/symmetric precache model, discarding!\n",
4480  ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
4481  peer->dead = 1;
4482  } else if ((peer->model & DUNDI_MODEL_OUTBOUND) && (peer->pcmodel & DUNDI_MODEL_INBOUND)) {
4483  ast_log(LOG_WARNING, "Peer '%s' may not be both outbound/symmetric model and inbound/symmetric precache model, discarding!\n",
4484  ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
4485  peer->dead = 1;
4486  } else if (!AST_LIST_EMPTY(&peer->include) && !(peer->model & DUNDI_MODEL_OUTBOUND) && !(peer->pcmodel & DUNDI_MODEL_INBOUND)) {
4487  ast_log(LOG_WARNING, "Peer '%s' is supposed to be included in outbound searches but isn't an outbound peer or inbound precache!\n",
4488  ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
4489  } else if (!AST_LIST_EMPTY(&peer->permit) && !(peer->model & DUNDI_MODEL_INBOUND) && !(peer->pcmodel & DUNDI_MODEL_OUTBOUND)) {
4490  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",
4491  ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
4492  } else {
4493  if (needregister) {
4494  peer->registerid = ast_sched_add(sched, 2000, do_register, peer);
4495  }
4496  if (ast_eid_cmp(&peer->eid, &empty_eid)) {
4497  qualify_peer(peer, 1);
4498  }
4499  }
4501 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
struct sockaddr_in addr
Definition: pbx_dundi.c:296
#define DUNDI_MODEL_SYMMETRIC
Definition: pbx_dundi.c:153
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Definition: netsock.c:222
static dundi_eid global_eid
Definition: pbx_dundi.c:189
int qualifyid
Definition: pbx_dundi.c:304
int ast_sched_add(struct sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
Adds a scheduled event Schedule an event to take place at some point in the future. callback will be called with data as the argument, when milliseconds into the future (approximately) If callback returns 0, no further events will be re-scheduled.
Definition: sched.c:446
#define DUNDI_PORT
Definition: dundi.h:30
#define LOG_WARNING
Definition: logger.h:144
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
int lineno
Definition: config.h:87
static void populate_addr(struct dundi_peer *peer, dundi_eid *eid)
Definition: pbx_dundi.c:4329
Definition: sched.c:57
static void destroy_permissions(struct permissionlist *permlist)
Definition: pbx_dundi.c:4127
int registerexpire
Definition: pbx_dundi.c:316
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
char outkey[80]
Definition: pbx_dundi.c:301
static void qualify_peer(struct dundi_peer *peer, int schedonly)
Definition: pbx_dundi.c:4306
static int do_register(const void *data)
Definition: pbx_dundi.c:4272
An Entity ID is essentially a MAC address, brief and unique.
Definition: utils.h:808
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
Definition: netsock.c:320
int registerid
Definition: pbx_dundi.c:303
const char * value
Definition: config.h:79
#define AST_SCHED_DEL(sched, id)
a loop construct to ensure that the scheduled task get deleted. The idea is that if we loop attemptin...
Definition: sched.h:51
#define DUNDI_MODEL_INBOUND
Definition: pbx_dundi.c:151
int ast_str_to_eid(struct ast_eid *eid, const char *s)
Convert a string into an EID.
Definition: netsock.c:305
static void append_permission(struct permissionlist *permlist, const char *s, int allow)
Definition: pbx_dundi.c:4183
static dundi_eid empty_eid
Definition: pbx_dundi.c:203
const char * name
Definition: config.h:77
dundi_eid us_eid
Definition: pbx_dundi.c:299
unsigned int dynamic
Definition: pbx_dundi.c:325
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#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:696
#define DEFAULT_MAXMS
Definition: chan_iax2.c:343
dundi_eid eid
Definition: pbx_dundi.c:295
char inkey[80]
Definition: pbx_dundi.c:300
struct dundi_peer::permissionlist permit
int pcmodel
Definition: pbx_dundi.c:323
struct permissionlist include
Definition: pbx_dundi.c:298
struct hostent * ast_gethostbyname(const char *host, struct ast_hostent *hp)
Thread-safe gethostbyname function to use in Asterisk.
Definition: utils.c:195
#define ast_calloc(a, b)
Definition: astmm.h:82
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
struct ast_variable * next
Definition: config.h:82
static struct hostent * hp
Definition: chan_skinny.c:1048
#define DUNDI_MODEL_OUTBOUND
Definition: pbx_dundi.c:152
static void build_secret ( char *  secret,
int  seclen 
)
static

Definition at line 2079 of file pbx_dundi.c.

References ast_base64encode(), and build_iv().

Referenced by check_password(), and load_password().

2080 {
2081  unsigned char tmp[16];
2082  char *s;
2083  build_iv(tmp);
2084  secret[0] = '\0';
2085  ast_base64encode(secret, tmp, sizeof(tmp), seclen);
2086  /* Eliminate potential bad characters */
2087  while((s = strchr(secret, ';'))) *s = '+';
2088  while((s = strchr(secret, '/'))) *s = '+';
2089  while((s = strchr(secret, ':'))) *s = '+';
2090  while((s = strchr(secret, '@'))) *s = '+';
2091 }
static void build_iv(unsigned char *iv)
Definition: pbx_dundi.c:522
int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
Encode data in base64.
Definition: utils.c:357
static char secret[50]
Definition: chan_h323.c:148
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 3452 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, 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().

3453 {
3454  struct dundi_peer *p;
3455  int x;
3456  int res;
3457  int pass;
3458  int allowconnect;
3459  char eid_str[20];
3460  AST_LIST_LOCK(&peers);
3461  AST_LIST_TRAVERSE(&peers, p, list) {
3462  if (modeselect == 1) {
3463  /* Send the precache to push upstreams only! */
3464  pass = has_permission(&p->permit, dr->dcontext) && (p->pcmodel & DUNDI_MODEL_OUTBOUND);
3465  allowconnect = 1;
3466  } else {
3467  /* Normal lookup / EID query */
3468  pass = has_permission(&p->include, dr->dcontext);
3469  allowconnect = p->model & DUNDI_MODEL_OUTBOUND;
3470  }
3471  if (skip) {
3472  if (!ast_eid_cmp(skip, &p->eid))
3473  pass = 0;
3474  }
3475  if (pass) {
3476  if (p->order <= order) {
3477  /* Check order first, then check cache, regardless of
3478  omissions, this gets us more likely to not have an
3479  affected answer. */
3480  if((nocache || !(res = cache_lookup(dr, &p->eid, dr->crc32, &dr->expiration)))) {
3481  res = 0;
3482  /* Make sure we haven't already seen it and that it won't
3483  affect our answer */
3484  for (x=0;avoid[x];x++) {
3485  if (!ast_eid_cmp(avoid[x], &p->eid) || !ast_eid_cmp(avoid[x], &p->us_eid)) {
3486  /* If not a direct connection, it affects our answer */
3487  if (directs && !directs[x])
3489  break;
3490  }
3491  }
3492  /* Make sure we can ask */
3493  if (allowconnect) {
3494  if (!avoid[x] && (!blockempty || !dundi_eid_zero(&p->us_eid))) {
3495  /* Check for a matching or 0 cache entry */
3496  append_transaction(dr, p, ttl, avoid);
3497  } else {
3498  ast_debug(1, "Avoiding '%s' in transaction\n", ast_eid_to_str(eid_str, sizeof(eid_str), avoid[x]));
3499  }
3500  }
3501  }
3502  *foundcache |= res;
3503  } else if (!*skipped || (p->order < *skipped))
3504  *skipped = p->order;
3505  }
3506  }
3508 }
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)
Definition: netsock.c:222
#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
struct dundi_peer::@318 list
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:265
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
Definition: netsock.c:320
static int has_permission(struct permissionlist *permlist, char *cont)
Definition: pbx_dundi.c:358
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
dundi_eid us_eid
Definition: pbx_dundi.c:299
static int cache_lookup(struct dundi_request *req, dundi_eid *peer_eid, uint32_t crc32, int *lowexpiration)
Definition: pbx_dundi.c:1224
uint32_t crc32
Definition: pbx_dundi.c:277
#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:3395
struct dundi_hint_metadata * hmd
Definition: pbx_dundi.c:271
dundi_eid eid
Definition: pbx_dundi.c:295
struct dundi_peer::permissionlist permit
int pcmodel
Definition: pbx_dundi.c:323
struct permissionlist include
Definition: pbx_dundi.c:298
int dundi_eid_zero(dundi_eid *eid)
Definition: dundi-parser.c:83
#define DUNDI_MODEL_OUTBOUND
Definition: pbx_dundi.c:152
static int cache_lookup ( struct dundi_request req,
dundi_eid peer_eid,
uint32_t  crc32,
int *  lowexpiration 
)
static

Definition at line 1224 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, dundi_request::respcount, and dundi_request::root_eid.

Referenced by build_transactions().

1225 {
1226  char key[256];
1227  char eid_str[20];
1228  char eidroot_str[20];
1229  time_t now;
1230  int res=0;
1231  int res2=0;
1232  char eid_str_full[20];
1233  char tmp[256]="";
1234  int x;
1235 
1236  time(&now);
1237  dundi_eid_to_str_short(eid_str, sizeof(eid_str), peer_eid);
1238  dundi_eid_to_str_short(eidroot_str, sizeof(eidroot_str), &req->root_eid);
1239  ast_eid_to_str(eid_str_full, sizeof(eid_str_full), peer_eid);
1240  snprintf(key, sizeof(key), "%s/%s/%s/e%08x", eid_str, req->number, req->dcontext, crc32);
1241  res |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration);
1242  snprintf(key, sizeof(key), "%s/%s/%s/e%08x", eid_str, req->number, req->dcontext, (unsigned)0);
1243  res |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration);
1244  snprintf(key, sizeof(key), "%s/%s/%s/r%s", eid_str, req->number, req->dcontext, eidroot_str);
1245  res |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration);
1246  x = 0;
1247  if (!req->respcount) {
1248  while(!res2) {
1249  /* Look and see if we have a hint that would preclude us from looking at this
1250  peer for this number. */
1251  if (!(tmp[x] = req->number[x]))
1252  break;
1253  x++;
1254  /* Check for hints */
1255  snprintf(key, sizeof(key), "hint/%s/%s/%s/e%08x", eid_str, tmp, req->dcontext, crc32);
1256  res2 |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration);
1257  snprintf(key, sizeof(key), "hint/%s/%s/%s/e%08x", eid_str, tmp, req->dcontext, (unsigned)0);
1258  res2 |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration);
1259  snprintf(key, sizeof(key), "hint/%s/%s/%s/r%s", eid_str, tmp, req->dcontext, eidroot_str);
1260  res2 |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration);
1261  if (res2) {
1262  if (strlen(tmp) > strlen(req->hmd->exten)) {
1263  /* Update meta data if appropriate */
1264  ast_copy_string(req->hmd->exten, tmp, sizeof(req->hmd->exten));
1265  }
1266  }
1267  }
1268  res |= res2;
1269  }
1270 
1271  return res;
1272 }
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Definition: netsock.c:222
char * dundi_eid_to_str_short(char *s, int maxlen, dundi_eid *eid)
Definition: dundi-parser.c:55
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:265
static int cache_lookup_internal(time_t now, struct dundi_request *req, char *key, char *eid_str_full, int *lowexpiration)
Definition: pbx_dundi.c:1152
char number[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:266
struct dundi_hint_metadata * hmd
Definition: pbx_dundi.c:271
char exten[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:224
dundi_eid root_eid
Definition: pbx_dundi.c:268
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static int cache_lookup_internal ( time_t  now,
struct dundi_request req,
char *  key,
char *  eid_str_full,
int *  lowexpiration 
)
static

Definition at line 1152 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, and dundi_result::weight.

Referenced by cache_lookup().

1153 {
1154  char data[1024];
1155  char *ptr, *term, *src;
1156  int tech;
1157  struct ast_flags flags;
1158  int weight;
1159  int length;
1160  int z;
1161  char fs[256];
1162 
1163  /* Build request string */
1164  if (!ast_db_get("dundi/cache", key, data, sizeof(data))) {
1165  time_t timeout;
1166  ptr = data;
1167  if (!ast_get_time_t(ptr, &timeout, 0, &length)) {
1168  int expiration = timeout - now;
1169  if (expiration > 0) {
1170  ast_debug(1, "Found cache expiring in %d seconds!\n", expiration);
1171  ptr += length + 1;
1172  while((sscanf(ptr, "%30d/%30d/%30d/%n", (int *)&(flags.flags), &weight, &tech, &length) == 3)) {
1173  ptr += length;
1174  term = strchr(ptr, '|');
1175  if (term) {
1176  *term = '\0';
1177  src = strrchr(ptr, '/');
1178  if (src) {
1179  *src = '\0';
1180  src++;
1181  } else
1182  src = "";
1183  ast_debug(1, "Found cached answer '%s/%s' originally from '%s' with flags '%s' on behalf of '%s'\n",
1184  tech2str(tech), ptr, src, dundi_flags2str(fs, sizeof(fs), flags.flags), eid_str_full);
1185  /* Make sure it's not already there */
1186  for (z=0;z<req->respcount;z++) {
1187  if ((req->dr[z].techint == tech) &&
1188  !strcmp(req->dr[z].dest, ptr))
1189  break;
1190  }
1191  if (z == req->respcount) {
1192  /* Copy into parent responses */
1193  ast_copy_flags(&(req->dr[req->respcount]), &flags, AST_FLAGS_ALL);
1194  req->dr[req->respcount].weight = weight;
1195  req->dr[req->respcount].techint = tech;
1196  req->dr[req->respcount].expiration = expiration;
1197  dundi_str_short_to_eid(&req->dr[req->respcount].eid, src);
1198  ast_eid_to_str(req->dr[req->respcount].eid_str,
1199  sizeof(req->dr[req->respcount].eid_str), &req->dr[req->respcount].eid);
1200  ast_copy_string(req->dr[req->respcount].dest, ptr,
1201  sizeof(req->dr[req->respcount].dest));
1202  ast_copy_string(req->dr[req->respcount].tech, tech2str(tech),
1203  sizeof(req->dr[req->respcount].tech));
1204  req->respcount++;
1206  } else if (req->dr[z].weight > weight)
1207  req->dr[z].weight = weight;
1208  ptr = term + 1;
1209  }
1210  }
1211  /* We found *something* cached */
1212  if (expiration < *lowexpiration)
1213  *lowexpiration = expiration;
1214  return 1;
1215  } else
1216  ast_db_del("dundi/cache", key);
1217  } else
1218  ast_db_del("dundi/cache", key);
1219  }
1220 
1221  return 0;
1222 }
int weight
Definition: dundi.h:227
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Definition: netsock.c:222
int ast_db_get(const char *family, const char *key, char *out, int outlen)
Get key value specified by family/key.
Definition: db.c:348
#define ast_clear_flag_nonstd(p, flag)
Definition: utils.h:180
static char * tech2str(int tech)
Definition: pbx_dundi.c:371
unsigned int flags
Definition: utils.h:201
struct dundi_result * dr
Definition: pbx_dundi.c:269
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: utils.c:2118
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
char tech[10]
Definition: dundi.h:232
char eid_str[20]
Definition: dundi.h:231
int expiration
Definition: dundi.h:228
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:271
Structure used to handle boolean flags.
Definition: utils.h:200
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: db.c:365
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
int dundi_str_short_to_eid(dundi_eid *eid, const char *s)
Definition: dundi-parser.c:71
char * dundi_flags2str(char *buf, int bufsiz, int flags)
Definition: dundi-parser.c:247
static int cache_save ( dundi_eid eidpeer,
struct dundi_request req,
int  start,
int  unaffected,
int  expiration,
int  push 
)
static

Definition at line 881 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, and dundi_result::weight.

Referenced by dundi_prop_precache(), and handle_command_response().

882 {
883  int x;
884  char key1[256];
885  char key2[256];
886  char data[1024];
887  char eidpeer_str[20];
888  char eidroot_str[20];
889  time_t timeout;
890 
891  if (expiration < 1)
892  expiration = dundi_cache_time;
893 
894  /* Keep pushes a little longer, cut pulls a little short */
895  if (push)
896  expiration += 10;
897  else
898  expiration -= 10;
899  if (expiration < 1)
900  expiration = 1;
901  dundi_eid_to_str_short(eidpeer_str, sizeof(eidpeer_str), eidpeer);
902  dundi_eid_to_str_short(eidroot_str, sizeof(eidroot_str), &req->root_eid);
903  snprintf(key1, sizeof(key1), "%s/%s/%s/e%08x", eidpeer_str, req->number, req->dcontext, unaffected ? 0 : req->crc32);
904  snprintf(key2, sizeof(key2), "%s/%s/%s/r%s", eidpeer_str, req->number, req->dcontext, eidroot_str);
905  /* Build request string */
906  time(&timeout);
907  timeout += expiration;
908  snprintf(data, sizeof(data), "%ld|", (long)(timeout));
909  for (x=start;x<req->respcount;x++) {
910  /* Skip anything with an illegal pipe in it */
911  if (strchr(req->dr[x].dest, '|'))
912  continue;
913  snprintf(data + strlen(data), sizeof(data) - strlen(data), "%u/%d/%d/%s/%s|",
914  req->dr[x].flags, req->dr[x].weight, req->dr[x].techint, req->dr[x].dest,
915  dundi_eid_to_str_short(eidpeer_str, sizeof(eidpeer_str), &req->dr[x].eid));
916  }
917  ast_db_put("dundi/cache", key1, data);
918  ast_db_put("dundi/cache", key2, data);
919  return 0;
920 }
int weight
Definition: dundi.h:227
static int dundi_cache_time
Definition: pbx_dundi.c:187
char * dundi_eid_to_str_short(char *s, int maxlen, dundi_eid *eid)
Definition: dundi-parser.c:55
struct dundi_result * dr
Definition: pbx_dundi.c:269
char dest[256]
Definition: dundi.h:233
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:265
char number[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:266
int techint
Definition: dundi.h:229
uint32_t crc32
Definition: pbx_dundi.c:277
dundi_eid eid
Definition: dundi.h:230
unsigned int flags
Definition: dundi.h:226
dundi_eid root_eid
Definition: pbx_dundi.c:268
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: db.c:260
static int cache_save_hint ( dundi_eid eidpeer,
struct dundi_request req,
struct dundi_hint hint,
int  expiration 
)
static

Definition at line 846 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, and dundi_request::root_eid.

Referenced by dundi_prop_precache(), and handle_command_response().

847 {
848  int unaffected;
849  char key1[256];
850  char key2[256];
851  char eidpeer_str[20];
852  char eidroot_str[20];
853  char data[80];
854  time_t timeout;
855 
856  if (expiration < 0)
857  expiration = dundi_cache_time;
858 
859  /* Only cache hint if "don't ask" is there... */
860  if (!ast_test_flag_nonstd(hint, htons(DUNDI_HINT_DONT_ASK)))
861  return 0;
862 
863  unaffected = ast_test_flag_nonstd(hint, htons(DUNDI_HINT_UNAFFECTED));
864 
865  dundi_eid_to_str_short(eidpeer_str, sizeof(eidpeer_str), eidpeer);
866  dundi_eid_to_str_short(eidroot_str, sizeof(eidroot_str), &req->root_eid);
867  snprintf(key1, sizeof(key1), "hint/%s/%s/%s/e%08x", eidpeer_str, hint->data, req->dcontext, unaffected ? 0 : req->crc32);
868  snprintf(key2, sizeof(key2), "hint/%s/%s/%s/r%s", eidpeer_str, hint->data, req->dcontext, eidroot_str);
869 
870  time(&timeout);
871  timeout += expiration;
872  snprintf(data, sizeof(data), "%ld|", (long)(timeout));
873 
874  ast_db_put("dundi/cache", key1, data);
875  ast_debug(1, "Caching hint at '%s'\n", key1);
876  ast_db_put("dundi/cache", key2, data);
877  ast_debug(1, "Caching hint at '%s'\n", key2);
878  return 0;
879 }
static int dundi_cache_time
Definition: pbx_dundi.c:187
char * dundi_eid_to_str_short(char *s, int maxlen, dundi_eid *eid)
Definition: dundi-parser.c:55
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:265
unsigned char data[0]
Definition: dundi.h:112
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
uint32_t crc32
Definition: pbx_dundi.c:277
dundi_eid root_eid
Definition: pbx_dundi.c:268
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: db.c:260
#define ast_test_flag_nonstd(p, flag)
Definition: utils.h:173
static void cancel_request ( struct dundi_request dr)
static

Definition at line 3426 of file pbx_dundi.c.

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

Referenced by dundi_lookup_internal(), and dundi_precache_internal().

3427 {
3428  struct dundi_transaction *trans;
3429 
3430  AST_LIST_LOCK(&peers);
3431  while ((trans = AST_LIST_REMOVE_HEAD(&dr->trans, parentlist))) {
3432  /* Orphan transaction from request */
3433  trans->parent = NULL;
3434  /* Send final cancel */
3435  dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
3436  }
3438 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
struct dundi_request * parent
Definition: pbx_dundi.c:259
#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:3062
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
struct dundi_request::@315 trans
#define DUNDI_COMMAND_CANCEL
Definition: dundi.h:171
struct dundi_transaction::@313 parentlist
static int check_key ( struct dundi_peer peer,
unsigned char *  newkey,
unsigned char *  newsig,
uint32_t  keycrc32 
)
static

Definition at line 1470 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().

1471 {
1472  unsigned char dst[128];
1473  int res;
1474  struct ast_key *key, *skey;
1475  char eid_str[20];
1476  ast_debug(1, "Expected '%08x' got '%08x'\n", peer->them_keycrc32, keycrc32);
1477  if (peer->them_keycrc32 && (peer->them_keycrc32 == keycrc32)) {
1478  /* A match */
1479  return 1;
1480  } else if (!newkey || !newsig)
1481  return 0;
1482  if (!memcmp(peer->rxenckey, newkey, 128) &&
1483  !memcmp(peer->rxenckey + 128, newsig, 128)) {
1484  /* By definition, a match */
1485  return 1;
1486  }
1487  /* Decrypt key */
1488  key = ast_key_get(peer->outkey, AST_KEY_PRIVATE);
1489  if (!key) {
1490  ast_log(LOG_NOTICE, "Unable to find key '%s' to decode shared key from '%s'\n",
1491  peer->outkey, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
1492  return -1;
1493  }
1494 
1495  skey = ast_key_get(peer->inkey, AST_KEY_PUBLIC);
1496  if (!skey) {
1497  ast_log(LOG_NOTICE, "Unable to find key '%s' to verify shared key from '%s'\n",
1498  peer->inkey, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
1499  return -1;
1500  }
1501 
1502  /* First check signature */
1503  res = ast_check_signature_bin(skey, (char *)newkey, 128, newsig);
1504  if (res)
1505  return 0;
1506 
1507  res = ast_decrypt_bin(dst, newkey, sizeof(dst), key);
1508  if (res != 16) {
1509  if (res >= 0)
1510  ast_log(LOG_NOTICE, "Weird, key decoded to the wrong size (%d)\n", res);
1511  return 0;
1512  }
1513  /* Decrypted, passes signature */
1514  ast_debug(1, "Wow, new key combo passed signature and decrypt!\n");
1515  memcpy(peer->rxenckey, newkey, 128);
1516  memcpy(peer->rxenckey + 128, newsig, 128);
1517  peer->them_keycrc32 = crc32(0L, peer->rxenckey, 128);
1518  ast_aes_set_decrypt_key(dst, &peer->them_dcx);
1519  ast_aes_set_encrypt_key(dst, &peer->them_ecx);
1520  return 1;
1521 }
int ast_decrypt_bin(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key)
Decrypt a message using a given private key.
Definition: res_crypto.c:331
int ast_check_signature_bin(struct ast_key *key, const char *msg, int msglen, const unsigned char *sig)
Check the authenticity of a message signature using a given public key.
Definition: res_crypto.c:411
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Definition: netsock.c:222
int ast_aes_set_encrypt_key(const unsigned char *key, ast_aes_encrypt_key *ctx)
Set an encryption key.
Definition: res_crypto.c:461
unsigned char rxenckey[256]
Definition: pbx_dundi.c:308
char outkey[80]
Definition: pbx_dundi.c:301
ast_aes_decrypt_key them_dcx
Definition: pbx_dundi.c:314
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#define AST_KEY_PRIVATE
Definition: crypto.h:43
ast_aes_encrypt_key them_ecx
Definition: pbx_dundi.c:313
int ast_aes_set_decrypt_key(const unsigned char *key, ast_aes_decrypt_key *ctx)
Set a decryption key.
Definition: res_crypto.c:466
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
uint32_t them_keycrc32
Definition: pbx_dundi.c:312
dundi_eid eid
Definition: pbx_dundi.c:295
char inkey[80]
Definition: pbx_dundi.c:300
#define AST_KEY_PUBLIC
Definition: crypto.h:42
struct ast_key * ast_key_get(const char *key, int type)
Retrieve a key.
Definition: res_crypto.c:136
static void check_password ( void  )
static

Definition at line 2146 of file pbx_dundi.c.

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

Referenced by network_thread().

2147 {
2148  char oldsecret[80];
2149  time_t now;
2150 
2151  time(&now);
2152 #if 0
2153  printf("%ld/%ld\n", now, rotatetime);
2154 #endif
2155  if ((now - rotatetime) >= 0) {
2156  /* Time to rotate keys */
2157  ast_copy_string(oldsecret, cursecret, sizeof(oldsecret));
2158  build_secret(cursecret, sizeof(cursecret));
2159  save_secret(cursecret, oldsecret);
2160  }
2161 }
static void save_secret(const char *newkey, const char *oldkey)
Definition: pbx_dundi.c:2094
static void build_secret(char *secret, int seclen)
Definition: pbx_dundi.c:2079
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static time_t rotatetime
Definition: pbx_dundi.c:202
static char cursecret[80]
Definition: pbx_dundi.c:200
static int check_request ( struct dundi_request dr)
static

Definition at line 3547 of file pbx_dundi.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, and AST_LIST_UNLOCK.

Referenced by dundi_lookup_internal().

3548 {
3549  struct dundi_request *cur;
3550 
3551  AST_LIST_LOCK(&peers);
3552  AST_LIST_TRAVERSE(&requests, cur, list) {
3553  if (cur == dr)
3554  break;
3555  }
3557 
3558  return cur ? 1 : 0;
3559 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
struct dundi_request::@316 list
#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
static char* complete_peer_helper ( const char *  line,
const char *  word,
int  pos,
int  state,
int  rpos 
)
static

Definition at line 2381 of file pbx_dundi.c.

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

Referenced by dundi_show_peer().

2382 {
2383  int which=0, len;
2384  char *ret = NULL;
2385  struct dundi_peer *p;
2386  char eid_str[20];
2387 
2388  if (pos != rpos)
2389  return NULL;
2390  AST_LIST_LOCK(&peers);
2391  len = strlen(word);
2392  AST_LIST_TRAVERSE(&peers, p, list) {
2393  const char *s = ast_eid_to_str(eid_str, sizeof(eid_str), &p->eid);
2394  if (!strncasecmp(word, s, len) && ++which > state) {
2395  ret = ast_strdup(s);
2396  break;
2397  }
2398  }
2400  return ret;
2401 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define ast_strdup(a)
Definition: astmm.h:109
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Definition: netsock.c:222
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
struct dundi_peer::@318 list
Definition: ael.tab.c:203
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:295
static struct dundi_transaction * create_transaction ( struct dundi_peer p)
static

Definition at line 2900 of file pbx_dundi.c.

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

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

2901 {
2902  struct dundi_transaction *trans;
2903  int tid;
2904 
2905  /* Don't allow creation of transactions to non-registered peers */
2906  if (p && !p->addr.sin_addr.s_addr)
2907  return NULL;
2908  tid = get_trans_id();
2909  if (tid < 1)
2910  return NULL;
2911  if (!(trans = ast_calloc(1, sizeof(*trans))))
2912  return NULL;
2913 
2914  if (global_storehistory) {
2915  trans->start = ast_tvnow();
2916  ast_set_flag(trans, FLAG_STOREHIST);
2917  }
2919  trans->autokillid = -1;
2920  if (p) {
2921  apply_peer(trans, p);
2922  if (!p->sentfullkey)
2924  }
2925  trans->strans = tid;
2926  AST_LIST_INSERT_HEAD(&alltrans, trans, all);
2927 
2928  return trans;
2929 }
static void apply_peer(struct dundi_transaction *trans, struct dundi_peer *p)
Definition: pbx_dundi.c:1276
struct sockaddr_in addr
Definition: pbx_dundi.c:296
#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:142
#define DUNDI_DEFAULT_RETRANS_TIMER
Definition: dundi.h:215
static int global_storehistory
Definition: pbx_dundi.c:191
static int get_trans_id(void)
Definition: pbx_dundi.c:469
unsigned short strans
Definition: pbx_dundi.c:251
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:696
#define ast_calloc(a, b)
Definition: astmm.h:82
struct dundi_transaction::@314 all
struct timeval start
Definition: pbx_dundi.c:238
int sentfullkey
Definition: pbx_dundi.c:305
static int decrypt_memcpy ( unsigned char *  dst,
unsigned char *  src,
int  len,
unsigned char *  iv,
ast_aes_decrypt_key dcx 
)
static

Definition at line 1367 of file pbx_dundi.c.

References ast_aes_decrypt().

Referenced by dundi_decrypt().

1368 {
1369  unsigned char lastblock[16];
1370  int x;
1371  memcpy(lastblock, iv, sizeof(lastblock));
1372  while(len > 0) {
1373  ast_aes_decrypt(src, dst, dcx);
1374  for (x=0;x<16;x++)
1375  dst[x] ^= lastblock[x];
1376  memcpy(lastblock, src, sizeof(lastblock));
1377  dst += 16;
1378  src += 16;
1379  len -= 16;
1380  }
1381  return 0;
1382 }
void ast_aes_decrypt(const unsigned char *in, unsigned char *out, const ast_aes_decrypt_key *ctx)
AES decrypt data.
Definition: res_crypto.c:476
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:244
static void deep_copy_peer ( struct dundi_peer peer_dst,
const struct dundi_peer peer_src 
)
static

Definition at line 1523 of file pbx_dundi.c.

References permission::allow, ast_calloc, AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, dundi_peer::include, permission::name, and dundi_peer::permit.

Referenced by handle_command_response().

1524 {
1525  struct permission *cur, *perm;
1526 
1527  memcpy(peer_dst, peer_src, sizeof(*peer_dst));
1528 
1529  memset(&peer_dst->permit, 0, sizeof(peer_dst->permit));
1530  memset(&peer_dst->include, 0, sizeof(peer_dst->permit));
1531 
1532  AST_LIST_TRAVERSE(&peer_src->permit, cur, list) {
1533  if (!(perm = ast_calloc(1, sizeof(*perm) + strlen(cur->name) + 1)))
1534  continue;
1535 
1536  perm->allow = cur->allow;
1537  strcpy(perm->name, cur->name);
1538 
1539  AST_LIST_INSERT_HEAD(&peer_dst->permit, perm, list);
1540  }
1541 
1542  AST_LIST_TRAVERSE(&peer_src->include, cur, list) {
1543  if (!(perm = ast_calloc(1, sizeof(*perm) + strlen(cur->name) + 1)))
1544  continue;
1545 
1546  perm->allow = cur->allow;
1547  strcpy(perm->name, cur->name);
1548 
1549  AST_LIST_INSERT_HEAD(&peer_dst->include, perm, list);
1550  }
1551 }
#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:696
struct dundi_peer::permissionlist permit
char name[0]
Definition: pbx_dundi.c:209
struct permissionlist include
Definition: pbx_dundi.c:298
#define ast_calloc(a, b)
Definition: astmm.h:82
struct permission::@310 list
static void destroy_map ( struct dundi_mapping map)
static

Definition at line 4146 of file pbx_dundi.c.

References ast_free, and dundi_mapping::weightstr.

Referenced by prune_mappings().

4147 {
4148  if (map->weightstr)
4149  ast_free(map->weightstr);
4150  ast_free(map);
4151 }
#define ast_free(a)
Definition: astmm.h:97
char * weightstr
Definition: pbx_dundi.c:286
static void destroy_packet ( struct dundi_packet pack,
int  needfree 
)
static

Definition at line 2947 of file pbx_dundi.c.

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

Referenced by ack_trans().

2948 {
2949  if (pack->parent)
2950  AST_LIST_REMOVE(&pack->parent->packets, pack, list);
2951  AST_SCHED_DEL(sched, pack->retransid);
2952  if (needfree)
2953  ast_free(pack);
2954 }
Definition: sched.c:57
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Definition: linkedlists.h:841
#define AST_SCHED_DEL(sched, id)
a loop construct to ensure that the scheduled task get deleted. The idea is that if we loop attemptin...
Definition: sched.h:51
struct dundi_transaction::packetlist packets
#define ast_free(a)
Definition: astmm.h:97
struct permission::@310 list
struct dundi_transaction * parent
Definition: pbx_dundi.c:216
static void destroy_packets ( struct packetlist *  p)
static

Definition at line 1978 of file pbx_dundi.c.

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

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

1979 {
1980  struct dundi_packet *pack;
1981 
1982  while ((pack = AST_LIST_REMOVE_HEAD(p, list))) {
1983  AST_SCHED_DEL(sched, pack->retransid);
1984  ast_free(pack);
1985  }
1986 }
Definition: sched.c:57
#define AST_SCHED_DEL(sched, id)
a loop construct to ensure that the scheduled task get deleted. The idea is that if we loop attemptin...
Definition: sched.h:51
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
#define ast_free(a)
Definition: astmm.h:97
struct dundi_packet::@311 list
static void destroy_peer ( struct dundi_peer peer)
static

Definition at line 4135 of file pbx_dundi.c.

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

Referenced by prune_peers().

4136 {
4137  AST_SCHED_DEL(sched, peer->registerid);
4138  if (peer->regtrans)
4139  destroy_trans(peer->regtrans, 0);
4140  AST_SCHED_DEL(sched, peer->qualifyid);
4141  destroy_permissions(&peer->permit);
4142  destroy_permissions(&peer->include);
4143  ast_free(peer);
4144 }
int qualifyid
Definition: pbx_dundi.c:304
Definition: sched.c:57
static void destroy_permissions(struct permissionlist *permlist)
Definition: pbx_dundi.c:4127
static void destroy_trans(struct dundi_transaction *trans, int fromtimeout)
Definition: pbx_dundi.c:2956
int registerid
Definition: pbx_dundi.c:303
#define AST_SCHED_DEL(sched, id)
a loop construct to ensure that the scheduled task get deleted. The idea is that if we loop attemptin...
Definition: sched.h:51
#define ast_free(a)
Definition: astmm.h:97
struct dundi_peer::permissionlist permit
struct permissionlist include
Definition: pbx_dundi.c:298
struct dundi_transaction * regtrans
Definition: pbx_dundi.c:320
static void destroy_permissions ( struct permissionlist *  permlist)
static

Definition at line 4127 of file pbx_dundi.c.

References ast_free, and AST_LIST_REMOVE_HEAD.

Referenced by build_peer(), and destroy_peer().

4128 {
4129  struct permission *perm;
4130 
4131  while ((perm = AST_LIST_REMOVE_HEAD(permlist, list)))
4132  ast_free(perm);
4133 }
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
#define ast_free(a)
Definition: astmm.h:97
struct permission::@310 list
static void destroy_trans ( struct dundi_transaction trans,
int  fromtimeout 
)
static

Definition at line 2956 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, LOG_NOTICE, LOG_WARNING, dundi_peer::lookups, dundi_peer::lookuptimes, dundi_peer::maxms, dundi_request::number, dundi_transaction::packets, dundi_transaction::parent, dundi_request::pfds, dundi_peer::qualtrans, dundi_peer::qualtx, dundi_peer::regtrans, dundi_transaction::start, dundi_transaction::them_eid, dundi_transaction::thread, and dundi_request::trans.

Referenced by abort_request(), destroy_peer(), do_autokill(), do_register(), dundi_lookup_thread(), dundi_precache_thread(), dundi_query_thread(), dundi_rexmit(), handle_frame(), precache_trans(), precache_transactions(), and qualify_peer().

2957 {
2958  struct dundi_peer *peer;
2959  int ms;
2960  int x;
2961  int cnt;
2962  char eid_str[20];
2964  AST_LIST_TRAVERSE(&peers, peer, list) {
2965  if (peer->regtrans == trans)
2966  peer->regtrans = NULL;
2967  if (peer->qualtrans == trans) {
2968  if (fromtimeout) {
2969  if (peer->lastms > -1)
2970  ast_log(LOG_NOTICE, "Peer '%s' has become UNREACHABLE!\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
2971  peer->lastms = -1;
2972  } else {
2973  ms = ast_tvdiff_ms(ast_tvnow(), peer->qualtx);
2974  if (ms < 1)
2975  ms = 1;
2976  if (ms < peer->maxms) {
2977  if ((peer->lastms >= peer->maxms) || (peer->lastms < 0))
2978  ast_log(LOG_NOTICE, "Peer '%s' has become REACHABLE!\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
2979  } else if (peer->lastms < peer->maxms) {
2980  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);
2981  }
2982  peer->lastms = ms;
2983  }
2984  peer->qualtrans = NULL;
2985  }
2986  if (ast_test_flag(trans, FLAG_STOREHIST)) {
2987  if (trans->parent && !ast_strlen_zero(trans->parent->number)) {
2988  if (!ast_eid_cmp(&trans->them_eid, &peer->eid)) {
2989  peer->avgms = 0;
2990  cnt = 0;
2991  if (peer->lookups[DUNDI_TIMING_HISTORY-1])
2993  for (x=DUNDI_TIMING_HISTORY-1;x>0;x--) {
2994  peer->lookuptimes[x] = peer->lookuptimes[x-1];
2995  peer->lookups[x] = peer->lookups[x-1];
2996  if (peer->lookups[x]) {
2997  peer->avgms += peer->lookuptimes[x];
2998  cnt++;
2999  }
3000  }
3001  peer->lookuptimes[0] = ast_tvdiff_ms(ast_tvnow(), trans->start);
3002  peer->lookups[0] = ast_malloc(strlen(trans->parent->number) + strlen(trans->parent->dcontext) + 2);
3003  if (peer->lookups[0]) {
3004  sprintf(peer->lookups[0], "%s@%s", trans->parent->number, trans->parent->dcontext);
3005  peer->avgms += peer->lookuptimes[0];
3006  cnt++;
3007  }
3008  if (cnt)
3009  peer->avgms /= cnt;
3010  }
3011  }
3012  }
3013  }
3014  }
3015  if (trans->parent) {
3016  /* Unlink from parent if appropriate */
3017  AST_LIST_REMOVE(&trans->parent->trans, trans, parentlist);
3018  if (AST_LIST_EMPTY(&trans->parent->trans)) {
3019  /* Wake up sleeper */
3020  if (trans->parent->pfds[1] > -1) {
3021  if (write(trans->parent->pfds[1], "killa!", 6) < 0) {
3022  ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
3023  }
3024  }
3025  }
3026  }
3027  /* Unlink from all trans */
3028  AST_LIST_REMOVE(&alltrans, trans, all);
3029  destroy_packets(&trans->packets);
3030  destroy_packets(&trans->lasttrans);
3031  AST_SCHED_DEL(sched, trans->autokillid);
3032  if (trans->thread) {
3033  /* If used by a thread, mark as dead and be done */
3034  ast_set_flag(trans, FLAG_DEAD);
3035  } else
3036  ast_free(trans);
3037 }
int pfds[2]
Definition: pbx_dundi.c:276
char * lookups[DUNDI_TIMING_HISTORY]
Definition: pbx_dundi.c:318
struct dundi_request * parent
Definition: pbx_dundi.c:259
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Definition: netsock.c:222
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define DUNDI_TIMING_HISTORY
Definition: pbx_dundi.c:156
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define LOG_WARNING
Definition: logger.h:144
Definition: sched.c:57
struct dundi_peer::@318 list
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
#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:90
int lookuptimes[DUNDI_TIMING_HISTORY]
Definition: pbx_dundi.c:317
struct packetlist lasttrans
Definition: pbx_dundi.c:258
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:265
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Definition: linkedlists.h:841
dundi_eid them_eid
Definition: pbx_dundi.c:242
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
Definition: netsock.c:320
int lastms
Definition: pbx_dundi.c:326
struct timeval qualtx
Definition: pbx_dundi.c:328
#define AST_SCHED_DEL(sched, id)
a loop construct to ensure that the scheduled task get deleted. The idea is that if we loop attemptin...
Definition: sched.h:51
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
struct dundi_transaction::packetlist packets
char number[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:266
struct dundi_transaction * qualtrans
Definition: pbx_dundi.c:321
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
int errno
#define ast_free(a)
Definition: astmm.h:97
dundi_eid eid
Definition: pbx_dundi.c:295
static void destroy_packets(struct packetlist *p)
Definition: pbx_dundi.c:1978
struct dundi_request::@315 trans
struct dundi_transaction * regtrans
Definition: pbx_dundi.c:320
struct timeval start
Definition: pbx_dundi.c:238
#define ast_malloc(a)
Definition: astmm.h:91
static int discover_transactions ( struct dundi_request dr)
static

Definition at line 3278 of file pbx_dundi.c.

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

Referenced by dundi_lookup_internal().

3279 {
3280  struct dundi_transaction *trans;
3281  AST_LIST_LOCK(&peers);
3282  AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) {
3283  dundi_discover(trans);
3284  }
3286  return 0;
3287 }
#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
static int dundi_discover(struct dundi_transaction *trans)
Definition: pbx_dundi.c:3166
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct dundi_request::@315 trans
struct dundi_transaction::@313 parentlist
static int do_autokill ( const void *  data)
static

Definition at line 3133 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().

3134 {
3135  struct dundi_transaction *trans = (struct dundi_transaction *)data;
3136  char eid_str[20];
3137  ast_log(LOG_NOTICE, "Transaction to '%s' took too long to ACK, destroying\n",
3138  ast_eid_to_str(eid_str, sizeof(eid_str), &trans->them_eid));
3139  trans->autokillid = -1;
3140  destroy_trans(trans, 0); /* We could actually set it to 1 instead of 0, but we won't ;-) */
3141  return 0;
3142 }
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Definition: netsock.c:222
static void destroy_trans(struct dundi_transaction *trans, int fromtimeout)
Definition: pbx_dundi.c:2956
dundi_eid them_eid
Definition: pbx_dundi.c:242
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
static int do_qualify ( const void *  data)
static

Definition at line 4298 of file pbx_dundi.c.

References qualify_peer(), and dundi_peer::qualifyid.

Referenced by qualify_peer().

4299 {
4300  struct dundi_peer *peer = (struct dundi_peer *)data;
4301  peer->qualifyid = -1;
4302  qualify_peer(peer, 0);
4303  return 0;
4304 }
int qualifyid
Definition: pbx_dundi.c:304
static void qualify_peer(struct dundi_peer *peer, int schedonly)
Definition: pbx_dundi.c:4306
static int do_register ( const void *  data)
static

Definition at line 4272 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().

4273 {
4274  struct dundi_ie_data ied;
4275  struct dundi_peer *peer = (struct dundi_peer *)data;
4276  char eid_str[20];
4277  char eid_str2[20];
4278  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));
4280  /* Destroy old transaction if there is one */
4281  if (peer->regtrans)
4282  destroy_trans(peer->regtrans, 0);
4283  peer->regtrans = create_transaction(peer);
4284  if (peer->regtrans) {
4286  memset(&ied, 0, sizeof(ied));
4290  dundi_send(peer->regtrans, DUNDI_COMMAND_REGREQ, 0, 0, &ied);
4291 
4292  } else
4293  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));
4294 
4295  return 0;
4296 }
#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)
Definition: netsock.c:222
int ast_sched_add(struct sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
Adds a scheduled event Schedule an event to take place at some point in the future. callback will be called with data as the argument, when milliseconds into the future (approximately) If callback returns 0, no further events will be re-scheduled.
Definition: sched.c:446
#define ast_set_flag(p, flag)
Definition: utils.h:70
Definition: sched.c:57
static int dundi_send(struct dundi_transaction *trans, int cmdresp, int flags, int final, struct dundi_ie_data *ied)
Definition: pbx_dundi.c:3062
dundi_eid us_eid
Definition: pbx_dundi.c:241
#define DUNDI_IE_VERSION
Definition: dundi.h:188
static void destroy_trans(struct dundi_transaction *trans, int fromtimeout)
Definition: pbx_dundi.c:2956
static int do_register(const void *data)
Definition: pbx_dundi.c:4272
int registerid
Definition: pbx_dundi.c:303
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static struct dundi_transaction * create_transaction(struct dundi_peer *p)
Definition: pbx_dundi.c:2900
#define DUNDI_IE_EID
Definition: dundi.h:182
dundi_eid us_eid
Definition: pbx_dundi.c:299
static int default_expiration
Definition: pbx_dundi.c:190
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
#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:295
#define DUNDI_COMMAND_REGREQ
Definition: dundi.h:169
struct dundi_transaction * regtrans
Definition: pbx_dundi.c:320
static int do_register_expire ( const void *  data)
static
Note
Called with the peers list already locked

Definition at line 1301 of file pbx_dundi.c.

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

Referenced by handle_command_response(), and populate_addr().

1302 {
1303  struct dundi_peer *peer = (struct dundi_peer *)data;
1304  char eid_str[20];
1305  ast_debug(1, "Register expired for '%s'\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
1306  peer->registerexpire = -1;
1307  peer->lastms = 0;
1308  memset(&peer->addr, 0, sizeof(peer->addr));
1309  return 0;
1310 }
struct sockaddr_in addr
Definition: pbx_dundi.c:296
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Definition: netsock.c:222
int registerexpire
Definition: pbx_dundi.c:316
int lastms
Definition: pbx_dundi.c:326
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
dundi_eid eid
Definition: pbx_dundi.c:295
static void drds_destroy ( struct dundi_result_datastore drds)
static

Definition at line 3952 of file pbx_dundi.c.

References ast_free.

Referenced by drds_destroy_cb(), and dundi_query_read().

3953 {
3954  ast_free(drds);
3955 }
#define ast_free(a)
Definition: astmm.h:97
static void drds_destroy_cb ( void *  data)
static

Definition at line 3957 of file pbx_dundi.c.

References drds_destroy().

3958 {
3959  struct dundi_result_datastore *drds = data;
3960  drds_destroy(drds);
3961 }
static void drds_destroy(struct dundi_result_datastore *drds)
Definition: pbx_dundi.c:3952
static int dundi_ack ( struct dundi_transaction trans,
int  final 
)
static

Definition at line 440 of file pbx_dundi.c.

References DUNDI_COMMAND_ACK, and dundi_send().

Referenced by handle_command_response(), and handle_frame().

441 {
442  return dundi_send(trans, DUNDI_COMMAND_ACK, 0, final, NULL);
443 }
static int dundi_send(struct dundi_transaction *trans, int cmdresp, int flags, int final, struct dundi_ie_data *ied)
Definition: pbx_dundi.c:3062
#define DUNDI_COMMAND_ACK
Definition: dundi.h:159
static int dundi_answer_entity ( struct dundi_transaction trans,
struct dundi_ies ies,
char *  ccontext 
)
static

Definition at line 791 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, 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().

792 {
793  struct dundi_query_state *st;
794  int totallen;
795  int x;
796  int skipfirst=0;
797  char eid_str[20];
798  char *s;
799  pthread_t lookupthread;
800 
801  if (ies->eidcount > 1) {
802  /* Since it is a requirement that the first EID is the authenticating host
803  and the last EID is the root, it is permissible that the first and last EID
804  could be the same. In that case, we should go ahead copy only the "root" section
805  since we will not need it for authentication. */
806  if (!ast_eid_cmp(ies->eids[0], ies->eids[ies->eidcount - 1]))
807  skipfirst = 1;
808  }
809  totallen = sizeof(struct dundi_query_state);
810  totallen += (ies->eidcount - skipfirst) * sizeof(dundi_eid);
811  st = ast_calloc(1, totallen);
812  if (st) {
814  memcpy(&st->reqeid, ies->reqeid, sizeof(st->reqeid));
815  st->trans = trans;
816  st->ttl = ies->ttl - 1;
817  if (st->ttl < 0)
818  st->ttl = 0;
819  s = st->fluffy;
820  for (x=skipfirst;ies->eids[x];x++) {
821  st->eids[x-skipfirst] = (dundi_eid *)s;
822  *st->eids[x-skipfirst] = *ies->eids[x];
823  s += sizeof(dundi_eid);
824  }
825  ast_debug(1, "Answering EID query for '%s@%s'!\n", ast_eid_to_str(eid_str, sizeof(eid_str), ies->reqeid), ies->called_context);
826 
827  trans->thread = 1;
828  if (ast_pthread_create_detached(&lookupthread, NULL, dundi_query_thread, st)) {
829  struct dundi_ie_data ied = { 0, };
830  trans->thread = 0;
831  ast_log(LOG_WARNING, "Unable to create thread!\n");
832  ast_free(st);
833  dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of threads");
834  dundi_send(trans, DUNDI_COMMAND_EIDRESPONSE, 0, 1, &ied);
835  return -1;
836  }
837  } else {
838  struct dundi_ie_data ied = { 0, };
840  dundi_send(trans, DUNDI_COMMAND_EIDRESPONSE, 0, 1, &ied);
841  return -1;
842  }
843  return 0;
844 }
dundi_eid * reqeid
Definition: dundi-parser.h:24
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:422
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Definition: netsock.c:222
struct ast_eid dundi_eid
Definition: dundi.h:32
#define LOG_WARNING
Definition: logger.h:144
dundi_eid * eids[DUNDI_MAX_STACK+1]
Definition: pbx_dundi.c:533
struct dundi_transaction * trans
Definition: pbx_dundi.c:541
#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:3062
dundi_eid reqeid
Definition: pbx_dundi.c:535
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:808
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
Definition: netsock.c:320
int eidcount
Definition: dundi-parser.h:25
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int dundi_ie_append_cause(struct dundi_ie_data *ied, unsigned char ie, unsigned char cause, char *data)
Definition: dundi-parser.c:499
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
char * called_context
Definition: dundi-parser.h:26
#define ast_free(a)
Definition: astmm.h:97
static void * dundi_query_thread(void *data)
Definition: pbx_dundi.c:736
#define DUNDI_COMMAND_EIDRESPONSE
Definition: dundi.h:163
#define ast_calloc(a, b)
Definition: astmm.h:82
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
char called_context[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:536
static int dundi_answer_query ( struct dundi_transaction trans,
struct dundi_ies ies,
char *  ccontext 
)
static

Definition at line 1069 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, dundi_mapping::list, LOG_WARNING, dundi_query_state::maps, dundi_mapping::next, dundi_query_state::nocache, dundi_query_state::nummaps, dundi_transaction::thread, dundi_query_state::trans, dundi_ies::ttl, and dundi_query_state::ttl.

Referenced by handle_command_response().

1070 {
1071  struct dundi_query_state *st;
1072  int totallen;
1073  int x;
1074  struct dundi_ie_data ied;
1075  char *s;
1076  struct dundi_mapping *cur;
1077  int mapcount = 0;
1078  int skipfirst = 0;
1079 
1080  pthread_t lookupthread;
1081  totallen = sizeof(struct dundi_query_state);
1082  /* Count matching map entries */
1083  AST_LIST_TRAVERSE(&mappings, cur, list) {
1084  if (!strcasecmp(cur->dcontext, ccontext))
1085  mapcount++;
1086  }
1087  /* If no maps, return -1 immediately */
1088  if (!mapcount)
1089  return -1;
1090 
1091  if (ies->eidcount > 1) {
1092  /* Since it is a requirement that the first EID is the authenticating host
1093  and the last EID is the root, it is permissible that the first and last EID
1094  could be the same. In that case, we should go ahead copy only the "root" section
1095  since we will not need it for authentication. */
1096  if (!ast_eid_cmp(ies->eids[0], ies->eids[ies->eidcount - 1]))
1097  skipfirst = 1;
1098  }
1099 
1100  totallen += mapcount * sizeof(struct dundi_mapping);
1101  totallen += (ies->eidcount - skipfirst) * sizeof(dundi_eid);
1102  st = ast_calloc(1, totallen);
1103  if (st) {
1105  ast_copy_string(st->called_number, ies->called_number, sizeof(st->called_number));
1106  st->trans = trans;
1107  st->ttl = ies->ttl - 1;
1108  st->nocache = ies->cbypass;
1109  if (st->ttl < 0)
1110  st->ttl = 0;
1111  s = st->fluffy;
1112  for (x=skipfirst;ies->eids[x];x++) {
1113  st->eids[x-skipfirst] = (dundi_eid *)s;
1114  *st->eids[x-skipfirst] = *ies->eids[x];
1115  st->directs[x-skipfirst] = ies->eid_direct[x];
1116  s += sizeof(dundi_eid);
1117  }
1118  /* Append mappings */
1119  x = 0;
1120  st->maps = (struct dundi_mapping *)s;
1121  AST_LIST_TRAVERSE(&mappings, cur, list) {
1122  if (!strcasecmp(cur->dcontext, ccontext)) {
1123  if (x < mapcount) {
1124  st->maps[x] = *cur;
1125  st->maps[x].list.next = NULL;
1126  x++;
1127  }
1128  }
1129  }
1130  st->nummaps = mapcount;
1131  ast_debug(1, "Answering query for '%s@%s'!\n", ies->called_number, ies->called_context);
1132  trans->thread = 1;
1133  if (ast_pthread_create_detached(&lookupthread, NULL, dundi_lookup_thread, st)) {
1134  trans->thread = 0;
1135  ast_log(LOG_WARNING, "Unable to create thread!\n");
1136  ast_free(st);
1137  memset(&ied, 0, sizeof(ied));
1138  dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of threads");
1139  dundi_send(trans, DUNDI_COMMAND_DPRESPONSE, 0, 1, &ied);
1140  return -1;
1141  }
1142  } else {
1143  ast_log(LOG_WARNING, "Out of memory!\n");
1144  memset(&ied, 0, sizeof(ied));
1145  dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of memory");
1146  dundi_send(trans, DUNDI_COMMAND_DPRESPONSE, 0, 1, &ied);
1147  return -1;
1148  }
1149  return 0;
1150 }
struct dundi_mapping::@317 list
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:283
char called_number[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:537
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:422
struct ast_eid dundi_eid
Definition: dundi.h:32
static void * dundi_lookup_thread(void *data)
Definition: pbx_dundi.c:639
#define LOG_WARNING
Definition: logger.h:144
dundi_eid * eids[DUNDI_MAX_STACK+1]
Definition: pbx_dundi.c:533
struct dundi_mapping * maps
Definition: pbx_dundi.c:538
struct dundi_transaction * trans
Definition: pbx_dundi.c:541
#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:3062
int eid_direct[DUNDI_MAX_STACK+1]
Definition: dundi-parser.h:23
char * called_number
Definition: dundi-parser.h:27
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:808
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
Definition: netsock.c:320
struct dundi_mapping * next
Definition: pbx_dundi.c:291
int eidcount
Definition: dundi-parser.h:25
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#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
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#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:97
int directs[DUNDI_MAX_STACK+1]
Definition: pbx_dundi.c:534
#define ast_calloc(a, b)
Definition: astmm.h:82
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
char called_context[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:536
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 4547 of file pbx_dundi.c.

References DUNDI_FLAG_CANMATCH, and dundi_helper().

4548 {
4549  return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_CANMATCH);
4550 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
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:4503
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static void dundi_debug_output ( const char *  data)
static

Definition at line 347 of file pbx_dundi.c.

References ast_verbose().

Referenced by load_module().

348 {
349  if (dundidebug)
350  ast_verbose("%s", data);
351 }
void ast_verbose(const char *fmt,...)
Definition: logger.c:1568
static int dundidebug
Definition: pbx_dundi.c:183
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 1384 of file pbx_dundi.c.

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

Referenced by handle_command_response().

1385 {
1386  int space = *dstlen;
1387  unsigned long bytes;
1388  struct dundi_hdr *h;
1389  unsigned char *decrypt_space;
1390  decrypt_space = ast_alloca(srclen);
1391  decrypt_memcpy(decrypt_space, src->encdata, srclen, src->iv, &trans->dcx);
1392  /* Setup header */
1393  h = (struct dundi_hdr *)dst;
1394  *h = *ohdr;
1395  bytes = space - 6;
1396  if (uncompress(dst + 6, &bytes, decrypt_space, srclen) != Z_OK) {
1397  ast_debug(1, "Ouch, uncompress failed :(\n");
1398  return NULL;
1399  }
1400  /* Update length */
1401  *dstlen = bytes + 6;
1402  /* Return new header */
1403  return h;
1404 }
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: utils.h:653
unsigned char encdata[0]
Definition: dundi.h:99
static int decrypt_memcpy(unsigned char *dst, unsigned char *src, int len, unsigned char *iv, ast_aes_decrypt_key *dcx)
Definition: pbx_dundi.c:1367
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
unsigned char iv[16]
Definition: dundi.h:98
ast_aes_decrypt_key dcx
Definition: pbx_dundi.c:244
static int dundi_discover ( struct dundi_transaction trans)
static

Definition at line 3166 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().

3167 {
3168  struct dundi_ie_data ied;
3169  int x;
3170  if (!trans->parent) {
3171  ast_log(LOG_WARNING, "Tried to discover a transaction with no parent?!?\n");
3172  return -1;
3173  }
3174  memset(&ied, 0, sizeof(ied));
3176  if (!dundi_eid_zero(&trans->us_eid))
3178  for (x=0;x<trans->eidcount;x++)
3179  dundi_ie_append_eid_appropriately(&ied, trans->parent->dcontext, &trans->eids[x], &trans->us_eid);
3182  dundi_ie_append_short(&ied, DUNDI_IE_TTL, trans->ttl);
3183  if (trans->parent->cbypass)
3185  if (trans->autokilltimeout)
3186  trans->autokillid = ast_sched_add(sched, trans->autokilltimeout, do_autokill, trans);
3187  return dundi_send(trans, DUNDI_COMMAND_DPDISCOVER, 0, 0, &ied);
3188 }
#define DUNDI_IE_EID_DIRECT
Definition: dundi.h:185
struct dundi_request * parent
Definition: pbx_dundi.c:259
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
int ast_sched_add(struct sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
Adds a scheduled event Schedule an event to take place at some point in the future. callback will be called with data as the argument, when milliseconds into the future (approximately) If callback returns 0, no further events will be re-scheduled.
Definition: sched.c:446
dundi_eid eids[DUNDI_MAX_STACK+1]
Definition: pbx_dundi.c:239
#define LOG_WARNING
Definition: logger.h:144
Definition: sched.c:57
static int dundi_send(struct dundi_transaction *trans, int cmdresp, int flags, int final, struct dundi_ie_data *ied)
Definition: pbx_dundi.c:3062
dundi_eid us_eid
Definition: pbx_dundi.c:241
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:265
static void dundi_ie_append_eid_appropriately(struct dundi_ie_data *ied, char *context, dundi_eid *eid, dundi_eid *us)
Definition: pbx_dundi.c:3144
#define DUNDI_IE_VERSION
Definition: dundi.h:188
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:3133
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:266
#define DUNDI_IE_CALLED_CONTEXT
Definition: dundi.h:183
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#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
#define DUNDI_IE_CALLED_NUMBER
Definition: dundi.h:184
int dundi_eid_zero(dundi_eid *eid)
Definition: dundi-parser.c:83
#define DUNDI_COMMAND_DPDISCOVER
Definition: dundi.h:160
#define DUNDI_IE_TTL
Definition: dundi.h:187
static char* dundi_do_lookup ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 2420 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, sort_results(), dundi_result::tech, ast_cli_entry::usage, and dundi_result::weight.

2421 {
2422  int res;
2423  char tmp[256];
2424  char fs[80] = "";
2425  char *context;
2426  int x;
2427  int bypass = 0;
2428  struct dundi_result dr[MAX_RESULTS];
2429  struct timeval start;
2430  switch (cmd) {
2431  case CLI_INIT:
2432  e->command = "dundi lookup";
2433  e->usage =
2434  "Usage: dundi lookup <number>[@context] [bypass]\n"
2435  " Lookup the given number within the given DUNDi context\n"
2436  "(or e164 if none is specified). Bypasses cache if 'bypass'\n"
2437  "keyword is specified.\n";
2438  return NULL;
2439  case CLI_GENERATE:
2440  return NULL;
2441  }
2442 
2443  if ((a->argc < 3) || (a->argc > 4))
2444  return CLI_SHOWUSAGE;
2445  if (a->argc > 3) {
2446  if (!strcasecmp(a->argv[3], "bypass"))
2447  bypass=1;
2448  else
2449  return CLI_SHOWUSAGE;
2450  }
2451  ast_copy_string(tmp, a->argv[2], sizeof(tmp));
2452  context = strchr(tmp, '@');
2453  if (context) {
2454  *context = '\0';
2455  context++;
2456  }
2457  start = ast_tvnow();
2458  res = dundi_lookup(dr, MAX_RESULTS, NULL, context, tmp, bypass);
2459 
2460  if (res < 0)
2461  ast_cli(a->fd, "DUNDi lookup returned error.\n");
2462  else if (!res)
2463  ast_cli(a->fd, "DUNDi lookup returned no results.\n");
2464  else
2465  sort_results(dr, res);
2466  for (x=0;x<res;x++) {
2467  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));
2468  ast_cli(a->fd, " from %s, expires in %d s\n", dr[x].eid_str, dr[x].expiration);
2469  }
2470  ast_cli(a->fd, "DUNDi lookup completed in %" PRIi64 " ms\n", ast_tvdiff_ms(ast_tvnow(), start));
2471  return CLI_SUCCESS;
2472 }
static float dr[4]
Definition: tdd.c:59
static void sort_results(struct dundi_result *results, int count)
Definition: pbx_dundi.c:2415
const int argc
Definition: cli.h:154
#define MAX_RESULTS
Definition: pbx_dundi.c:145
Definition: cli.h:146
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:90
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
const int fd
Definition: cli.h:153
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 unspec...
Definition: pbx_dundi.c:3678
const char *const * argv
Definition: cli.h:155
#define CLI_SHOWUSAGE
Definition: cli.h:44
char * command
Definition: cli.h:180
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
char * dundi_flags2str(char *buf, int bufsiz, int flags)
Definition: dundi-parser.c:247
static char* dundi_do_precache ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 2474 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, and ast_cli_entry::usage.

2475 {
2476  int res;
2477  char tmp[256];
2478  char *context;
2479  struct timeval start;
2480  switch (cmd) {
2481  case CLI_INIT:
2482  e->command = "dundi precache";
2483  e->usage =
2484  "Usage: dundi precache <number>[@context]\n"
2485  " Lookup the given number within the given DUNDi context\n"
2486  "(or e164 if none is specified) and precaches the results to any\n"
2487  "upstream DUNDi push servers.\n";
2488  return NULL;
2489  case CLI_GENERATE:
2490  return NULL;
2491  }
2492  if ((a->argc < 3) || (a->argc > 3))
2493  return CLI_SHOWUSAGE;
2494  ast_copy_string(tmp, a->argv[2], sizeof(tmp));
2495  context = strchr(tmp, '@');
2496  if (context) {
2497  *context = '\0';
2498  context++;
2499  }
2500  start = ast_tvnow();
2501  res = dundi_precache(context, tmp);
2502 
2503  if (res < 0)
2504  ast_cli(a->fd, "DUNDi precache returned error.\n");
2505  else if (!res)
2506  ast_cli(a->fd, "DUNDi precache returned no error.\n");
2507  ast_cli(a->fd, "DUNDi lookup completed in %" PRIi64 " ms\n", ast_tvdiff_ms(ast_tvnow(), start));
2508  return CLI_SUCCESS;
2509 }
int dundi_precache(const char *dcontext, const char *number)
Pre-cache to push upstream peers.
Definition: pbx_dundi.c:3821
const int argc
Definition: cli.h:154
Definition: cli.h:146
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:90
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
const int fd
Definition: cli.h:153
const char *const * argv
Definition: cli.h:155
#define CLI_SHOWUSAGE
Definition: cli.h:44
char * command
Definition: cli.h:180
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static char* dundi_do_query ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 2511 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, dundi_entity_info::org, dundi_entity_info::orgunit, dundi_entity_info::phone, dundi_entity_info::stateprov, and ast_cli_entry::usage.

2512 {
2513  int res;
2514  char tmp[256];
2515  char *context;
2516  dundi_eid eid;
2517  struct dundi_entity_info dei;
2518  switch (cmd) {
2519  case CLI_INIT:
2520  e->command = "dundi query";
2521  e->usage =
2522  "Usage: dundi query <entity>[@context]\n"
2523  " Attempts to retrieve contact information for a specific\n"
2524  "DUNDi entity identifier (EID) within a given DUNDi context (or\n"
2525  "e164 if none is specified).\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  if (ast_str_to_eid(&eid, a->argv[2])) {
2533  ast_cli(a->fd, "'%s' is not a valid EID!\n", a->argv[2]);
2534  return CLI_SHOWUSAGE;
2535  }
2536  ast_copy_string(tmp, a->argv[2], sizeof(tmp));
2537  context = strchr(tmp, '@');
2538  if (context) {
2539  *context = '\0';
2540  context++;
2541  }
2542  res = dundi_query_eid(&dei, context, eid);
2543  if (res < 0)
2544  ast_cli(a->fd, "DUNDi Query EID returned error.\n");
2545  else if (!res)
2546  ast_cli(a->fd, "DUNDi Query EID returned no results.\n");
2547  else {
2548  ast_cli(a->fd, "DUNDi Query EID succeeded:\n");
2549  ast_cli(a->fd, "Department: %s\n", dei.orgunit);
2550  ast_cli(a->fd, "Organization: %s\n", dei.org);
2551  ast_cli(a->fd, "City/Locality: %s\n", dei.locality);
2552  ast_cli(a->fd, "State/Province: %s\n", dei.stateprov);
2553  ast_cli(a->fd, "Country: %s\n", dei.country);
2554  ast_cli(a->fd, "E-mail: %s\n", dei.email);
2555  ast_cli(a->fd, "Phone: %s\n", dei.phone);
2556  ast_cli(a->fd, "IP Address: %s\n", dei.ipaddr);
2557  }
2558  return CLI_SUCCESS;
2559 }
const int argc
Definition: cli.h:154
Definition: cli.h:146
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:3874
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
An Entity ID is essentially a MAC address, brief and unique.
Definition: utils.h:808
const int fd
Definition: cli.h:153
int ast_str_to_eid(struct ast_eid *eid, const char *s)
Convert a string into an EID.
Definition: netsock.c:305
const char *const * argv
Definition: cli.h:155
#define CLI_SHOWUSAGE
Definition: cli.h:44
char * command
Definition: cli.h:180
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static int dundi_encrypt ( struct dundi_transaction trans,
struct dundi_packet pack 
)
static

Definition at line 1406 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, 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().

1407 {
1408  unsigned char *compress_space;
1409  int len;
1410  int res;
1411  unsigned long bytes;
1412  struct dundi_ie_data ied;
1413  struct dundi_peer *peer;
1414  unsigned char iv[16];
1415  len = pack->datalen + pack->datalen / 100 + 42;
1416  compress_space = ast_alloca(len);
1417  memset(compress_space, 0, len);
1418  /* We care about everthing save the first 6 bytes of header */
1419  bytes = len;
1420  res = compress(compress_space, &bytes, pack->data + 6, pack->datalen - 6);
1421  if (res != Z_OK) {
1422  ast_debug(1, "Ouch, compression failed!\n");
1423  return -1;
1424  }
1425  memset(&ied, 0, sizeof(ied));
1426  /* Say who we are */
1427  if (!pack->h->iseqno && !pack->h->oseqno) {
1428  /* Need the key in the first copy */
1429  if (!(peer = find_peer(&trans->them_eid)))
1430  return -1;
1431  if (update_key(peer))
1432  return -1;
1433  if (!peer->sentfullkey)
1435  /* Append key data */
1436  dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid);
1437  if (ast_test_flag(trans, FLAG_SENDFULLKEY)) {
1438  dundi_ie_append_raw(&ied, DUNDI_IE_SHAREDKEY, peer->txenckey, 128);
1439  dundi_ie_append_raw(&ied, DUNDI_IE_SIGNATURE, peer->txenckey + 128, 128);
1440  } else {
1442  }
1443  /* Setup contexts */
1444  trans->ecx = peer->us_ecx;
1445  trans->dcx = peer->us_dcx;
1446 
1447  /* We've sent the full key */
1448  peer->sentfullkey = 1;
1449  }
1450  /* Build initialization vector */
1451  build_iv(iv);
1452  /* Add the field, rounded up to 16 bytes */
1453  dundi_ie_append_encdata(&ied, DUNDI_IE_ENCDATA, iv, NULL, ((bytes + 15) / 16) * 16);
1454  /* Copy the data */
1455  if ((ied.pos + bytes) >= sizeof(ied.buf)) {
1456  ast_log(LOG_NOTICE, "Final packet too large!\n");
1457  return -1;
1458  }
1459  encrypt_memcpy(ied.buf + ied.pos, compress_space, bytes, iv, &trans->ecx);
1460  ied.pos += ((bytes + 15) / 16) * 16;
1461  /* Reconstruct header */
1462  pack->datalen = sizeof(struct dundi_hdr);
1463  pack->h->cmdresp = DUNDI_COMMAND_ENCRYPT;
1464  pack->h->cmdflags = 0;
1465  memcpy(pack->h->ies, ied.buf, ied.pos);
1466  pack->datalen += ied.pos;
1467  return 0;
1468 }
ast_aes_encrypt_key ecx
Definition: pbx_dundi.c:243
int dundi_ie_append_eid(struct dundi_ie_data *ied, unsigned char ie, dundi_eid *eid)
Definition: dundi-parser.c:610
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: utils.h:653
#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:1351
#define DUNDI_COMMAND_ENCRYPT
Definition: dundi.h:172
unsigned char cmdresp
Definition: dundi.h:39
dundi_eid us_eid
Definition: pbx_dundi.c:241
unsigned char oseqno
Definition: dundi.h:38
dundi_eid them_eid
Definition: pbx_dundi.c:242
unsigned char data[0]
Definition: pbx_dundi.c:219
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:309
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#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:311
unsigned char cmdflags
Definition: dundi.h:40
static void build_iv(unsigned char *iv)
Definition: pbx_dundi.c:522
#define DUNDI_IE_EID
Definition: dundi.h:182
unsigned char ies[0]
Definition: dundi.h:41
static struct dundi_peer * find_peer(dundi_eid *eid)
Definition: pbx_dundi.c:504
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
ast_aes_encrypt_key us_ecx
Definition: pbx_dundi.c:310
static int update_key(struct dundi_peer *peer)
Definition: pbx_dundi.c:1312
unsigned char txenckey[256]
Definition: pbx_dundi.c:307
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:244
struct dundi_hdr * h
Definition: pbx_dundi.c:214
int sentfullkey
Definition: pbx_dundi.c:305
unsigned char iseqno
Definition: dundi.h:37
static void dundi_error_output ( const char *  data)
static

Definition at line 353 of file pbx_dundi.c.

References ast_log(), and LOG_WARNING.

Referenced by load_module().

354 {
355  ast_log(LOG_WARNING, "%s", data);
356 }
#define LOG_WARNING
Definition: logger.h:144
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
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 4552 of file pbx_dundi.c.

References ast_log(), ast_strlen_zero(), ast_test_flag, context, DUNDI_FLAG_EXISTS, dundi_lookup(), ast_channel::exten, LOG_NOTICE, LOG_WARNING, ast_channel::macroexten, pbx_builtin_getvar_helper(), pbx_exec(), pbx_findapp(), S_OR, and sort_results().

4553 {
4554  struct dundi_result results[MAX_RESULTS];
4555  int res;
4556  int x=0;
4557  char req[1024];
4558  const char *dundiargs;
4559  struct ast_app *dial;
4560 
4561  if (!strncasecmp(context, "macro-", 6)) {
4562  if (!chan) {
4563  ast_log(LOG_NOTICE, "Can't use macro mode without a channel!\n");
4564  return -1;
4565  }
4566  /* If done as a macro, use macro extension */
4567  if (!strcasecmp(exten, "s")) {
4568  exten = pbx_builtin_getvar_helper(chan, "ARG1");
4569  if (ast_strlen_zero(exten))
4570  exten = chan->macroexten;
4571  if (ast_strlen_zero(exten))
4572  exten = chan->exten;
4573  if (ast_strlen_zero(exten)) {
4574  ast_log(LOG_WARNING, "Called in Macro mode with no ARG1 or MACRO_EXTEN?\n");
4575  return -1;
4576  }
4577  }
4578  if (ast_strlen_zero(data))
4579  data = "e164";
4580  } else {
4581  if (ast_strlen_zero(data))
4582  data = context;
4583  }
4584  res = dundi_lookup(results, MAX_RESULTS, chan, data, exten, 0);
4585  if (res > 0) {
4586  sort_results(results, res);
4587  for (x=0;x<res;x++) {
4588  if (ast_test_flag(results + x, DUNDI_FLAG_EXISTS)) {
4589  if (!--priority)
4590  break;
4591  }
4592  }
4593  }
4594  if (x < res) {
4595  /* Got a hit! */
4596  dundiargs = pbx_builtin_getvar_helper(chan, "DUNDIDIALARGS");
4597  snprintf(req, sizeof(req), "%s/%s,,%s", results[x].tech, results[x].dest,
4598  S_OR(dundiargs, ""));
4599  dial = pbx_findapp("Dial");
4600  if (dial)
4601  res = pbx_exec(chan, dial, req);
4602  } else
4603  res = -1;
4604  return res;
4605 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition: pbx.c:1537
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition: pbx.c:1497
static void sort_results(struct dundi_result *results, int count)
Definition: pbx_dundi.c:2415
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define LOG_WARNING
Definition: logger.h:144
#define MAX_RESULTS
Definition: pbx_dundi.c:145
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Definition: pbx.c:10475
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
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 unspec...
Definition: pbx_dundi.c:3678
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
char macroexten[AST_MAX_EXTENSION]
Definition: channel.h:871
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
ast_app: A registered application
Definition: pbx.c:971
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
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 4542 of file pbx_dundi.c.

References DUNDI_FLAG_EXISTS, and dundi_helper().

4543 {
4544  return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_EXISTS);
4545 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
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:4503
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static char* dundi_flush ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 2322 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, dundi_peer::lookups, dundi_peer::lookuptimes, and ast_cli_entry::usage.

2323 {
2324  int stats = 0;
2325  switch (cmd) {
2326  case CLI_INIT:
2327  e->command = "dundi flush [stats]";
2328  e->usage =
2329  "Usage: dundi flush [stats]\n"
2330  " Flushes DUNDi answer cache, used primarily for debug. If\n"
2331  "'stats' is present, clears timer statistics instead of normal\n"
2332  "operation.\n";
2333  return NULL;
2334  case CLI_GENERATE:
2335  return NULL;
2336  }
2337  if ((a->argc < 2) || (a->argc > 3))
2338  return CLI_SHOWUSAGE;
2339  if (a->argc > 2) {
2340  if (!strcasecmp(a->argv[2], "stats"))
2341  stats = 1;
2342  else
2343  return CLI_SHOWUSAGE;
2344  }
2345  if (stats) {
2346  /* Flush statistics */
2347  struct dundi_peer *p;
2348  int x;
2349  AST_LIST_LOCK(&peers);
2350  AST_LIST_TRAVERSE(&peers, p, list) {
2351  for (x = 0;x < DUNDI_TIMING_HISTORY; x++) {
2352  if (p->lookups[x])
2353  ast_free(p->lookups[x]);
2354  p->lookups[x] = NULL;
2355  p->lookuptimes[x] = 0;
2356  }
2357  p->avgms = 0;
2358  }
2360  } else {
2361  ast_db_deltree("dundi/cache", NULL);
2362  ast_cli(a->fd, "DUNDi Cache Flushed\n");
2363  }
2364  return CLI_SUCCESS;
2365 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
char * lookups[DUNDI_TIMING_HISTORY]
Definition: pbx_dundi.c:318
#define DUNDI_TIMING_HISTORY
Definition: pbx_dundi.c:156
const int argc
Definition: cli.h:154
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
Definition: cli.h:146
struct dundi_peer::@318 list
int lookuptimes[DUNDI_TIMING_HISTORY]
Definition: pbx_dundi.c:317
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
const int fd
Definition: cli.h:153
const char *const * argv
Definition: cli.h:155
#define CLI_SHOWUSAGE
Definition: cli.h:44
#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:97
char * command
Definition: cli.h:180
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
int ast_db_deltree(const char *family, const char *keytree)
Delete one or more entries in astdb If both parameters are NULL, the entire database will be purged...
Definition: db.c:241
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 4503 of file pbx_dundi.c.

References ast_log(), ast_strlen_zero(), ast_test_flag, context, dundi_lookup(), ast_channel::exten, LOG_NOTICE, LOG_WARNING, ast_channel::macroexten, and pbx_builtin_getvar_helper().

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

4504 {
4505  struct dundi_result results[MAX_RESULTS];
4506  int res;
4507  int x;
4508  int found = 0;
4509  if (!strncasecmp(context, "macro-", 6)) {
4510  if (!chan) {
4511  ast_log(LOG_NOTICE, "Can't use macro mode without a channel!\n");
4512  return -1;
4513  }
4514  /* If done as a macro, use macro extension */
4515  if (!strcasecmp(exten, "s")) {
4516  exten = pbx_builtin_getvar_helper(chan, "ARG1");
4517  if (ast_strlen_zero(exten))
4518  exten = chan->macroexten;
4519  if (ast_strlen_zero(exten))
4520  exten = chan->exten;
4521  if (ast_strlen_zero(exten)) {
4522  ast_log(LOG_WARNING, "Called in Macro mode with no ARG1 or MACRO_EXTEN?\n");
4523  return -1;
4524  }
4525  }
4526  if (ast_strlen_zero(data))
4527  data = "e164";
4528  } else {
4529  if (ast_strlen_zero(data))
4530  data = context;
4531  }
4532  res = dundi_lookup(results, MAX_RESULTS, chan, data, exten, 0);
4533  for (x=0;x<res;x++) {
4534  if (ast_test_flag(results + x, flag))
4535  found++;
4536  }
4537  if (found >= priority)
4538  return 1;
4539  return 0;
4540 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define LOG_WARNING
Definition: logger.h:144
#define MAX_RESULTS
Definition: pbx_dundi.c:145
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Definition: pbx.c:10475
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
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 unspec...
Definition: pbx_dundi.c:3678
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
char macroexten[AST_MAX_EXTENSION]
Definition: channel.h:871
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
static void dundi_ie_append_eid_appropriately ( struct dundi_ie_data ied,
char *  context,
dundi_eid eid,
dundi_eid us 
)
static

Definition at line 3144 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(), and dundi_peer::include.

Referenced by dundi_discover().

3145 {
3146  struct dundi_peer *p;
3147  if (!ast_eid_cmp(eid, us)) {
3149  return;
3150  }
3151  AST_LIST_LOCK(&peers);
3152  AST_LIST_TRAVERSE(&peers, p, list) {
3153  if (!ast_eid_cmp(&p->eid, eid)) {
3154  if (has_permission(&p->include, context))
3156  else
3157  dundi_ie_append_eid(ied, DUNDI_IE_EID, eid);
3158  break;
3159  }
3160  }
3161  if (!p)
3162  dundi_ie_append_eid(ied, DUNDI_IE_EID, eid);
3164 }
#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
struct dundi_peer::@318 list
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
Definition: netsock.c:320
static int has_permission(struct permissionlist *permlist, char *cont)
Definition: pbx_dundi.c:358
#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:295
struct permissionlist include
Definition: pbx_dundi.c:298
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
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 3678 of file pbx_dundi.c.

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

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

3679 {
3680  struct dundi_hint_metadata hmd;
3681  dundi_eid *avoid[1] = { NULL, };
3682  int direct[1] = { 0, };
3683  int expiration = dundi_cache_time;
3684  memset(&hmd, 0, sizeof(hmd));
3686  return dundi_lookup_internal(result, maxret, chan, dcontext, number, dundi_ttl, 0, &hmd, &expiration, cbypass, 0, NULL, avoid, direct);
3687 }
static int dundi_cache_time
Definition: pbx_dundi.c:187
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:3576
An Entity ID is essentially a MAC address, brief and unique.
Definition: utils.h:808
Number structure.
Definition: app_followme.c:109
static int dundi_ttl
Definition: pbx_dundi.c:185
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 3576 of file pbx_dundi.c.

References abort_request(), 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, ast_channel::name, dundi_request::number, optimize_transactions(), dundi_request::pfds, register_request(), dundi_request::respcount, dundi_request::root_eid, dundi_request::trans, and unregister_request().

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

3577 {
3578  int res;
3579  struct dundi_request dr, *pending;
3580  dundi_eid *rooteid=NULL;
3581  int x;
3582  int ttlms;
3583  int ms;
3584  int foundcache;
3585  int skipped=0;
3586  int order=0;
3587  char eid_str[20];
3588  struct timeval start;
3589 
3590  /* Don't do anthing for a hungup channel */
3591  if (chan && ast_check_hangup(chan))
3592  return 0;
3593 
3594  ttlms = DUNDI_FLUFF_TIME + ttl * DUNDI_TTL_TIME;
3595 
3596  for (x=0;avoid[x];x++)
3597  rooteid = avoid[x];
3598  /* Now perform real check */
3599  memset(&dr, 0, sizeof(dr));
3600  if (pipe(dr.pfds)) {
3601  ast_log(LOG_WARNING, "pipe failed: %s\n" , strerror(errno));
3602  return -1;
3603  }
3604  dr.dr = result;
3605  dr.hmd = hmd;
3606  dr.maxcount = maxret;
3607  dr.expiration = *expiration;
3608  dr.cbypass = cbypass;
3609  dr.crc32 = avoid_crc32(avoid);
3610  ast_copy_string(dr.dcontext, dcontext ? dcontext : "e164", sizeof(dr.dcontext));
3611  ast_copy_string(dr.number, number, sizeof(dr.number));
3612  if (rooteid)
3613  dr.root_eid = *rooteid;
3614  res = register_request(&dr, &pending);
3615  if (res) {
3616  /* Already a request */
3617  if (rooteid && !ast_eid_cmp(&dr.root_eid, &pending->root_eid)) {
3618  /* This is on behalf of someone else. Go ahead and close this out since
3619  they'll get their answer anyway. */
3620  ast_debug(1, "Oooh, duplicate request for '%s@%s' for '%s'\n",
3621  dr.number,dr.dcontext,ast_eid_to_str(eid_str, sizeof(eid_str), &dr.root_eid));
3622  close(dr.pfds[0]);
3623  close(dr.pfds[1]);
3624  return -2;
3625  } else {
3626  /* Wait for the cache to populate */
3627  ast_debug(1, "Waiting for similar request for '%s@%s' for '%s'\n",
3628  dr.number,dr.dcontext,ast_eid_to_str(eid_str, sizeof(eid_str), &pending->root_eid));
3629  start = ast_tvnow();
3630  while(check_request(pending) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms) && (!chan || !ast_check_hangup(chan))) {
3631  /* XXX Would be nice to have a way to poll/select here XXX */
3632  /* XXX this is a busy wait loop!!! */
3633  usleep(1);
3634  }
3635  /* Continue on as normal, our cache should kick in */
3636  }
3637  }
3638  /* Create transactions */
3639  do {
3640  order = skipped;
3641  skipped = 0;
3642  foundcache = 0;
3643  build_transactions(&dr, ttl, order, &foundcache, &skipped, blockempty, cbypass, modeselect, skip, avoid, direct);
3644  } while (skipped && !foundcache && AST_LIST_EMPTY(&dr.trans));
3645  /* If no TTL, abort and return 0 now after setting TTL expired hint. Couldn't
3646  do this earlier because we didn't know if we were going to have transactions
3647  or not. */
3648  if (!ttl) {
3650  abort_request(&dr);
3652  close(dr.pfds[0]);
3653  close(dr.pfds[1]);
3654  return 0;
3655  }
3656 
3657  /* Optimize transactions */
3658  optimize_transactions(&dr, order);
3659  /* Actually perform transactions */
3661  /* Wait for transaction to come back */
3662  start = ast_tvnow();
3663  while (!AST_LIST_EMPTY(&dr.trans) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms) && (!chan || !ast_check_hangup(chan))) {
3664  ms = 100;
3665  ast_waitfor_n_fd(dr.pfds, 1, &ms, NULL);
3666  }
3667  if (chan && ast_check_hangup(chan))
3668  ast_debug(1, "Hrm, '%s' hungup before their query for %s@%s finished\n", chan->name, dr.number, dr.dcontext);
3669  cancel_request(&dr);
3671  res = dr.respcount;
3672  *expiration = dr.expiration;
3673  close(dr.pfds[0]);
3674  close(dr.pfds[1]);
3675  return res;
3676 }
static float dr[4]
Definition: tdd.c:59
static int discover_transactions(struct dundi_request *dr)
Definition: pbx_dundi.c:3278
#define DUNDI_FLUFF_TIME
Definition: dundi.h:211
static int register_request(struct dundi_request *dr, struct dundi_request **pending)
Definition: pbx_dundi.c:3510
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Definition: netsock.c:222
#define LOG_WARNING
Definition: logger.h:144
static void cancel_request(struct dundi_request *dr)
Definition: pbx_dundi.c:3426
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
#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:90
An Entity ID is essentially a MAC address, brief and unique.
Definition: utils.h:808
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
Definition: netsock.c:320
Number structure.
Definition: app_followme.c:109
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception)
Waits for input on an fd.
Definition: channel.c:3176
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:806
#define DUNDI_TTL_TIME
Definition: dundi.h:212
static unsigned long avoid_crc32(dundi_eid *avoid[])
Definition: pbx_dundi.c:3561
static void unregister_request(struct dundi_request *dr)
Definition: pbx_dundi.c:3540
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int errno
static void abort_request(struct dundi_request *dr)
Definition: pbx_dundi.c:3440
dundi_eid root_eid
Definition: pbx_dundi.c:268
static int check_request(struct dundi_request *dr)
Definition: pbx_dundi.c:3547
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#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:3337
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:3452
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 562 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, 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, dundi_mapping::options, pbx_substitute_variables_varshead(), dundi_result::tech, dundi_mapping::tech, tech2str(), dundi_result::techint, and dundi_result::weight.

Referenced by dundi_lookup_thread(), and precache_trans().

563 {
564  struct ast_flags flags = {0};
565  int x;
566  if (!ast_strlen_zero(map->lcontext)) {
567  if (ast_exists_extension(NULL, map->lcontext, called_number, 1, NULL))
569  if (ast_canmatch_extension(NULL, map->lcontext, called_number, 1, NULL))
571  if (ast_matchmore_extension(NULL, map->lcontext, called_number, 1, NULL))
573  if (ast_ignore_pattern(map->lcontext, called_number))
575 
576  /* Clearly we can't say 'don't ask' anymore if we found anything... */
577  if (ast_test_flag(&flags, AST_FLAGS_ALL))
579 
581  /* Skip partial answers */
583  }
584  if (ast_test_flag(&flags, AST_FLAGS_ALL)) {
585  struct varshead headp;
586  struct ast_var_t *newvariable;
587  ast_set_flag(&flags, map->options & 0xffff);
588  ast_copy_flags(dr + anscnt, &flags, AST_FLAGS_ALL);
589  dr[anscnt].techint = map->tech;
590  dr[anscnt].weight = get_mapping_weight(map);
591  dr[anscnt].expiration = dundi_cache_time;
592  ast_copy_string(dr[anscnt].tech, tech2str(map->tech), sizeof(dr[anscnt].tech));
593  dr[anscnt].eid = *us_eid;
594  ast_eid_to_str(dr[anscnt].eid_str, sizeof(dr[anscnt].eid_str), &dr[anscnt].eid);
595  if (ast_test_flag(&flags, DUNDI_FLAG_EXISTS)) {
597  if ((newvariable = ast_var_assign("NUMBER", called_number))) {
598  AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
599  }
600  if ((newvariable = ast_var_assign("EID", dr[anscnt].eid_str))) {
601  AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
602  }
603  if ((newvariable = ast_var_assign("SECRET", cursecret))) {
604  AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
605  }
606  if ((newvariable = ast_var_assign("IPADDR", ipaddr))) {
607  AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
608  }
609  pbx_substitute_variables_varshead(&headp, map->dest, dr[anscnt].dest, sizeof(dr[anscnt].dest));
610  while ((newvariable = AST_LIST_REMOVE_HEAD(&headp, entries)))
611  ast_var_delete(newvariable);
612  } else
613  dr[anscnt].dest[0] = '\0';
614  anscnt++;
615  } else {
616  /* No answers... Find the fewest number of digits from the
617  number for which we have no answer. */
618  char tmp[AST_MAX_EXTENSION + 1] = "";
619  for (x = 0; x < (sizeof(tmp) - 1); x++) {
620  tmp[x] = called_number[x];
621  if (!tmp[x])
622  break;
623  if (!ast_canmatch_extension(NULL, map->lcontext, tmp, 1, NULL)) {
624  /* Oops found something we can't match. If this is longer
625  than the running hint, we have to consider it */
626  if (strlen(tmp) > strlen(hmd->exten)) {
627  ast_copy_string(hmd->exten, tmp, sizeof(hmd->exten));
628  }
629  break;
630  }
631  }
632  }
633  }
634  return anscnt;
635 }
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:5420
char dest[512]
Definition: pbx_dundi.c:290
static int get_mapping_weight(struct dundi_mapping *map)
Definition: pbx_dundi.c:548
int weight
Definition: dundi.h:227
char lcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:284
static int dundi_cache_time
Definition: pbx_dundi.c:187
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Definition: netsock.c:222
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ast_clear_flag_nonstd(p, flag)
Definition: utils.h:180
struct ast_var_t * ast_var_assign(const char *name, const char *value)
Definition: chanvars.c:41
#define ast_set_flag(p, flag)
Definition: utils.h:70
static char * tech2str(int tech)
Definition: pbx_dundi.c:371
unsigned int flags
Definition: utils.h:201
int ast_ignore_pattern(const char *context, const char *pattern)
Checks to see if a number should be ignored.
Definition: pbx.c:8650
char dest[256]
Definition: dundi.h:233
#define ast_copy_flags(dest, src, flagz)
Definition: utils.h:84
void ast_var_delete(struct ast_var_t *var)
Definition: chanvars.c:63
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:5415
#define DUNDI_FLAG_INTERNAL_NOPARTIAL
Definition: pbx_dundi.c:168
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#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:818
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:5400
static char ipaddr[80]
Definition: pbx_dundi.c:201
int techint
Definition: dundi.h:229
dundi_eid eid
Definition: dundi.h:230
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:696
struct ast_var_t::@158 entries
#define AST_FLAGS_ALL
Definition: utils.h:196
char exten[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:224
Structure used to handle boolean flags.
Definition: utils.h:200
#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:666
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static char cursecret[80]
Definition: pbx_dundi.c:200
void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count)
Definition: pbx.c:4682
static void* dundi_lookup_thread ( void *  data)
static

Definition at line 639 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, dundi_query_state::nocache, dundi_query_state::nummaps, dundi_transaction::thread, dundi_query_state::trans, dundi_query_state::ttl, dundi_transaction::us_eid, and dundi_result::weight.

Referenced by dundi_answer_query().

640 {
641  struct dundi_query_state *st = data;
642  struct dundi_result dr[MAX_RESULTS];
643  struct dundi_ie_data ied;
644  struct dundi_hint_metadata hmd;
645  char eid_str[20];
646  int res, x;
647  int ouranswers=0;
648  int max = 999999;
649  int expiration = dundi_cache_time;
650 
651  ast_debug(1, "Whee, looking up '%s@%s' for '%s'\n", st->called_number, st->called_context,
652  st->eids[0] ? ast_eid_to_str(eid_str, sizeof(eid_str), st->eids[0]) : "ourselves");
653  memset(&ied, 0, sizeof(ied));
654  memset(&dr, 0, sizeof(dr));
655  memset(&hmd, 0, sizeof(hmd));
656  /* Assume 'don't ask for anything' and 'unaffected', no TTL expired */
658  for (x=0;x<st->nummaps;x++)
659  ouranswers = dundi_lookup_local(dr, st->maps + x, st->called_number, &st->trans->us_eid, ouranswers, &hmd);
660  if (ouranswers < 0)
661  ouranswers = 0;
662  for (x=0;x<ouranswers;x++) {
663  if (dr[x].weight < max)
664  max = dr[x].weight;
665  }
666 
667  if (max) {
668  /* If we do not have a canonical result, keep looking */
669  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);
670  if (res > 0) {
671  /* Append answer in result */
672  ouranswers += res;
673  } else {
674  if ((res < -1) && (!ouranswers))
675  dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_DUPLICATE, "Duplicate Request Pending");
676  }
677  }
679  /* Truncate if "don't ask" isn't present */
681  hmd.exten[0] = '\0';
682  if (ast_test_flag(st->trans, FLAG_DEAD)) {
683  ast_debug(1, "Our transaction went away!\n");
684  st->trans->thread = 0;
685  destroy_trans(st->trans, 0);
686  } else {
687  for (x=0;x<ouranswers;x++) {
688  /* Add answers */
689  if (dr[x].expiration && (expiration > dr[x].expiration))
690  expiration = dr[x].expiration;
691  dundi_ie_append_answer(&ied, DUNDI_IE_ANSWER, &dr[x].eid, dr[x].techint, dr[x].flags, dr[x].weight, dr[x].dest);
692  }
693  dundi_ie_append_hint(&ied, DUNDI_IE_HINT, hmd.flags, hmd.exten);
694  dundi_ie_append_short(&ied, DUNDI_IE_EXPIRATION, expiration);
695  dundi_send(st->trans, DUNDI_COMMAND_DPRESPONSE, 0, 1, &ied);
696  st->trans->thread = 0;
697  }
699  ast_free(st);
700  return NULL;
701 }
static float dr[4]
Definition: tdd.c:59
#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:562
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
char called_number[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:537
static int dundi_cache_time
Definition: pbx_dundi.c:187
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Definition: netsock.c:222
#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:533
struct dundi_mapping * maps
Definition: pbx_dundi.c:538
struct dundi_transaction * trans
Definition: pbx_dundi.c:541
#define DUNDI_IE_CAUSE
Definition: dundi.h:191
#define MAX_RESULTS
Definition: pbx_dundi.c:145
static int dundi_send(struct dundi_transaction *trans, int cmdresp, int flags, int final, struct dundi_ie_data *ied)
Definition: pbx_dundi.c:3062
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:3576
dundi_eid us_eid
Definition: pbx_dundi.c:241
static void destroy_trans(struct dundi_transaction *trans, int fromtimeout)
Definition: pbx_dundi.c:2956
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#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
#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:223
#define ast_free(a)
Definition: astmm.h:97
int directs[DUNDI_MAX_STACK+1]
Definition: pbx_dundi.c:534
#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:536
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 4607 of file pbx_dundi.c.

References DUNDI_FLAG_MATCHMORE, and dundi_helper().

4608 {
4609  return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_MATCHMORE);
4610 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
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:4503
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
int dundi_precache ( const char *  context,
const char *  number 
)

Pre-cache to push upstream peers.

Definition at line 3821 of file pbx_dundi.c.

References dundi_precache_internal().

Referenced by dundi_do_precache(), and process_precache().

3822 {
3823  dundi_eid *avoid[1] = { NULL, };
3825 }
An Entity ID is essentially a MAC address, brief and unique.
Definition: utils.h:808
Number structure.
Definition: app_followme.c:109
static int dundi_ttl
Definition: pbx_dundi.c:185
static int dundi_precache_internal(const char *context, const char *number, int ttl, dundi_eid *avoids[])
Definition: pbx_dundi.c:3749
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static void dundi_precache_full ( void  )
static

Definition at line 3725 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, LOG_NOTICE, and reschedule_precache().

Referenced by set_config().

3726 {
3727  struct dundi_mapping *cur;
3728  struct ast_context *con;
3729  struct ast_exten *e;
3730 
3731  AST_LIST_TRAVERSE(&mappings, cur, list) {
3732  ast_log(LOG_NOTICE, "Should precache context '%s'\n", cur->dcontext);
3734  con = NULL;
3735  while ((con = ast_walk_contexts(con))) {
3736  if (strcasecmp(cur->lcontext, ast_get_context_name(con)))
3737  continue;
3738  /* Found the match, now queue them all up */
3739  ast_rdlock_context(con);
3740  e = NULL;
3741  while ((e = ast_walk_context_extensions(con, e)))
3743  ast_unlock_context(con);
3744  }
3746  }
3747 }
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:11065
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:884
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:283
char lcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:284
int ast_rdlock_contexts(void)
Read locks the context list.
Definition: pbx.c:11042
struct ast_exten * ast_walk_context_extensions(struct ast_context *con, struct ast_exten *priority)
Definition: pbx.c:11179
struct ast_context * ast_walk_contexts(struct ast_context *con)
Definition: pbx.c:11174
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:11073
static void reschedule_precache(const char *number, const char *context, int expiration)
Definition: pbx_dundi.c:3689
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:11047
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
const char * ast_get_extension_name(struct ast_exten *exten)
Definition: pbx.c:11083
#define LOG_NOTICE
Definition: logger.h:133
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
ast_context: An extension context
Definition: pbx.c:955
int ast_rdlock_context(struct ast_context *con)
Read locks a given context.
Definition: pbx.c:11060
static int dundi_precache_internal ( const char *  context,
const char *  number,
int  ttl,
dundi_eid avoids[] 
)
static

Definition at line 3749 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, LOG_NOTICE, LOG_WARNING, MAX_RESULTS, dundi_request::maxcount, dundi_request::number, optimize_transactions(), dundi_request::pfds, precache_transactions(), reschedule_precache(), and dundi_request::trans.

Referenced by dundi_precache(), and dundi_precache_thread().

3750 {
3751  struct dundi_request dr;
3752  struct dundi_hint_metadata hmd;
3753  struct dundi_result dr2[MAX_RESULTS];
3754  struct timeval start;
3755  struct dundi_mapping *maps = NULL, *cur;
3756  int nummaps = 0;
3757  int foundanswers;
3758  int foundcache, skipped, ttlms, ms;
3759  if (!context)
3760  context = "e164";
3761  ast_debug(1, "Precache internal (%s@%s)!\n", number, context);
3762 
3763  AST_LIST_LOCK(&peers);
3764  AST_LIST_TRAVERSE(&mappings, cur, list) {
3765  if (!strcasecmp(cur->dcontext, context))
3766  nummaps++;
3767  }
3768  if (nummaps) {
3769  maps = ast_alloca(nummaps * sizeof(*maps));
3770  nummaps = 0;
3771  AST_LIST_TRAVERSE(&mappings, cur, list) {
3772  if (!strcasecmp(cur->dcontext, context))
3773  maps[nummaps++] = *cur;
3774  }
3775  }
3777  if (!nummaps) {
3778  return -1;
3779  }
3780  ttlms = DUNDI_FLUFF_TIME + ttl * DUNDI_TTL_TIME;
3781  memset(&dr2, 0, sizeof(dr2));
3782  memset(&dr, 0, sizeof(dr));
3783  memset(&hmd, 0, sizeof(hmd));
3784  dr.dr = dr2;
3785  ast_copy_string(dr.number, number, sizeof(dr.number));
3786  ast_copy_string(dr.dcontext, context ? context : "e164", sizeof(dr.dcontext));
3787  dr.maxcount = MAX_RESULTS;
3788  dr.expiration = dundi_cache_time;
3789  dr.hmd = &hmd;
3790  dr.pfds[0] = dr.pfds[1] = -1;
3791  if (pipe(dr.pfds) < 0) {
3792  ast_log(LOG_WARNING, "pipe() failed: %s\n", strerror(errno));
3793  return -1;
3794  }
3795  build_transactions(&dr, ttl, 0, &foundcache, &skipped, 0, 1, 1, NULL, avoids, NULL);
3797  foundanswers = 0;
3798  precache_transactions(&dr, maps, nummaps, &dr.expiration, &foundanswers);
3799  if (foundanswers) {
3800  if (dr.expiration > 0)
3801  reschedule_precache(dr.number, dr.dcontext, dr.expiration);
3802  else
3803  ast_log(LOG_NOTICE, "Weird, expiration = %d, but need to precache for %s@%s?!\n", dr.expiration, dr.number, dr.dcontext);
3804  }
3805  start = ast_tvnow();
3806  while (!AST_LIST_EMPTY(&dr.trans) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms)) {
3807  if (dr.pfds[0] > -1) {
3808  ms = 100;
3809  ast_waitfor_n_fd(dr.pfds, 1, &ms, NULL);
3810  } else
3811  usleep(1);
3812  }
3813  cancel_request(&dr);
3814  if (dr.pfds[0] > -1) {
3815  close(dr.pfds[0]);
3816  close(dr.pfds[1]);
3817  }
3818  return 0;
3819 }
static float dr[4]
Definition: tdd.c:59
struct dundi_mapping::@317 list
#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:3289
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: utils.h:653
static int dundi_cache_time
Definition: pbx_dundi.c:187
#define LOG_WARNING
Definition: logger.h:144
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define MAX_RESULTS
Definition: pbx_dundi.c:145
static void cancel_request(struct dundi_request *dr)
Definition: pbx_dundi.c:3426
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
#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:90
Number structure.
Definition: app_followme.c:109
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception)
Waits for input on an fd.
Definition: channel.c:3176
static void reschedule_precache(const char *number, const char *context, int expiration)
Definition: pbx_dundi.c:3689
#define DUNDI_TTL_TIME
Definition: dundi.h:212
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
int errno
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static int optimize_transactions(struct dundi_request *dr, int order)
Definition: pbx_dundi.c:3337
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:3452
static void* dundi_precache_thread ( void *  data)
static

Definition at line 703 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_send(), dundi_query_state::eids, dundi_hint_metadata::exten, FLAG_DEAD, dundi_transaction::thread, dundi_query_state::trans, and dundi_query_state::ttl.

Referenced by dundi_prop_precache().

704 {
705  struct dundi_query_state *st = data;
706  struct dundi_ie_data ied;
707  struct dundi_hint_metadata hmd;
708  char eid_str[20];
709 
710  ast_debug(1, "Whee, precaching '%s@%s' for '%s'\n", st->called_number, st->called_context,
711  st->eids[0] ? ast_eid_to_str(eid_str, sizeof(eid_str), st->eids[0]) : "ourselves");
712  memset(&ied, 0, sizeof(ied));
713 
714  /* Now produce precache */
716 
718  /* Truncate if "don't ask" isn't present */
720  hmd.exten[0] = '\0';
721  if (ast_test_flag(st->trans, FLAG_DEAD)) {
722  ast_debug(1, "Our transaction went away!\n");
723  st->trans->thread = 0;
724  destroy_trans(st->trans, 0);
725  } else {
726  dundi_send(st->trans, DUNDI_COMMAND_PRECACHERP, 0, 1, &ied);
727  st->trans->thread = 0;
728  }
730  ast_free(st);
731  return NULL;
732 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
char called_number[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:537
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Definition: netsock.c:222
#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:533
struct dundi_transaction * trans
Definition: pbx_dundi.c:541
static int dundi_send(struct dundi_transaction *trans, int cmdresp, int flags, int final, struct dundi_ie_data *ied)
Definition: pbx_dundi.c:3062
static void destroy_trans(struct dundi_transaction *trans, int fromtimeout)
Definition: pbx_dundi.c:2956
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#define ast_free(a)
Definition: astmm.h:97
static int dundi_precache_internal(const char *context, const char *number, int ttl, dundi_eid *avoids[])
Definition: pbx_dundi.c:3749
#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:536
static int dundi_prop_precache ( struct dundi_transaction trans,
struct dundi_ies ies,
char *  ccontext 
)
static

Definition at line 922 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_hint_metadata::flags, dundi_result::flags, dundi_query_state::fluffy, dundi_ies::hint, dundi_request::hmd, dundi_mapping::list, LOG_NOTICE, LOG_WARNING, dundi_query_state::maps, MAX_RESULTS, dundi_request::maxcount, dundi_mapping::next, dundi_query_state::nocache, 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().

923 {
924  struct dundi_query_state *st;
925  int totallen;
926  int x,z;
927  struct dundi_ie_data ied;
928  char *s;
929  struct dundi_result dr2[MAX_RESULTS];
930  struct dundi_request dr;
931  struct dundi_hint_metadata hmd;
932 
933  struct dundi_mapping *cur;
934  int mapcount;
935  int skipfirst = 0;
936 
937  pthread_t lookupthread;
938 
939  memset(&dr2, 0, sizeof(dr2));
940  memset(&dr, 0, sizeof(dr));
941  memset(&hmd, 0, sizeof(hmd));
942 
943  /* Forge request structure to hold answers for cache */
945  dr.dr = dr2;
946  dr.maxcount = MAX_RESULTS;
947  dr.expiration = dundi_cache_time;
948  dr.hmd = &hmd;
949  dr.pfds[0] = dr.pfds[1] = -1;
950  trans->parent = &dr;
951  ast_copy_string(dr.dcontext, ies->called_context ? ies->called_context : "e164", sizeof(dr.dcontext));
952  ast_copy_string(dr.number, ies->called_number, sizeof(dr.number));
953 
954  for (x=0;x<ies->anscount;x++) {
955  if (trans->parent->respcount < trans->parent->maxcount) {
956  /* Make sure it's not already there */
957  for (z=0;z<trans->parent->respcount;z++) {
958  if ((trans->parent->dr[z].techint == ies->answers[x]->protocol) &&
959  !strcmp(trans->parent->dr[z].dest, (char *)ies->answers[x]->data))
960  break;
961  }
962  if (z == trans->parent->respcount) {
963  /* Copy into parent responses */
964  trans->parent->dr[trans->parent->respcount].flags = ntohs(ies->answers[x]->flags);
965  trans->parent->dr[trans->parent->respcount].techint = ies->answers[x]->protocol;
966  trans->parent->dr[trans->parent->respcount].weight = ntohs(ies->answers[x]->weight);
967  trans->parent->dr[trans->parent->respcount].eid = ies->answers[x]->eid;
968  if (ies->expiration > 0)
969  trans->parent->dr[trans->parent->respcount].expiration = ies->expiration;
970  else
972  ast_eid_to_str(trans->parent->dr[trans->parent->respcount].eid_str,
973  sizeof(trans->parent->dr[trans->parent->respcount].eid_str),
974  &ies->answers[x]->eid);
975  ast_copy_string(trans->parent->dr[trans->parent->respcount].dest, (char *)ies->answers[x]->data,
976  sizeof(trans->parent->dr[trans->parent->respcount].dest));
977  ast_copy_string(trans->parent->dr[trans->parent->respcount].tech, tech2str(ies->answers[x]->protocol),
978  sizeof(trans->parent->dr[trans->parent->respcount].tech));
979  trans->parent->respcount++;
981  } else if (trans->parent->dr[z].weight > ies->answers[x]->weight) {
982  /* Update weight if appropriate */
983  trans->parent->dr[z].weight = ies->answers[x]->weight;
984  }
985  } else
986  ast_log(LOG_NOTICE, "Dropping excessive answers in precache for %s@%s\n",
987  trans->parent->number, trans->parent->dcontext);
988 
989  }
990  /* Save all the results (if any) we had. Even if no results, still cache lookup. */
991  cache_save(&trans->them_eid, trans->parent, 0, 0, ies->expiration, 1);
992  if (ies->hint)
993  cache_save_hint(&trans->them_eid, trans->parent, ies->hint, ies->expiration);
994 
995  totallen = sizeof(struct dundi_query_state);
996  /* Count matching map entries */
997  mapcount = 0;
998  AST_LIST_TRAVERSE(&mappings, cur, list) {
999  if (!strcasecmp(cur->dcontext, ccontext))
1000  mapcount++;
1001  }
1002 
1003  /* If no maps, return -1 immediately */
1004  if (!mapcount)
1005  return -1;
1006 
1007  if (ies->eidcount > 1) {
1008  /* Since it is a requirement that the first EID is the authenticating host
1009  and the last EID is the root, it is permissible that the first and last EID
1010  could be the same. In that case, we should go ahead copy only the "root" section
1011  since we will not need it for authentication. */
1012  if (!ast_eid_cmp(ies->eids[0], ies->eids[ies->eidcount - 1]))
1013  skipfirst = 1;
1014  }
1015 
1016  /* Prepare to run a query and then propagate that as necessary */
1017  totallen += mapcount * sizeof(struct dundi_mapping);
1018  totallen += (ies->eidcount - skipfirst) * sizeof(dundi_eid);
1019  st = ast_calloc(1, totallen);
1020  if (st) {
1021  ast_copy_string(st->called_context, dr.dcontext, sizeof(st->called_context));
1022  ast_copy_string(st->called_number, ies->called_number, sizeof(st->called_number));
1023  st->trans = trans;
1024  st->ttl = ies->ttl - 1;
1025  st->nocache = ies->cbypass;
1026  if (st->ttl < 0)
1027  st->ttl = 0;
1028  s = st->fluffy;
1029  for (x=skipfirst;ies->eids[x];x++) {
1030  st->eids[x-skipfirst] = (dundi_eid *)s;
1031  *st->eids[x-skipfirst] = *ies->eids[x];
1032  st->directs[x-skipfirst] = ies->eid_direct[x];
1033  s += sizeof(dundi_eid);
1034  }
1035  /* Append mappings */
1036  x = 0;
1037  st->maps = (struct dundi_mapping *)s;
1038  AST_LIST_TRAVERSE(&mappings, cur, list) {
1039  if (!strcasecmp(cur->dcontext, ccontext)) {
1040  if (x < mapcount) {
1041  st->maps[x] = *cur;
1042  st->maps[x].list.next = NULL;
1043  x++;
1044  }
1045  }
1046  }
1047  st->nummaps = mapcount;
1048  ast_debug(1, "Forwarding precache for '%s@%s'!\n", ies->called_number, ies->called_context);
1049  trans->thread = 1;
1050  if (ast_pthread_create_detached(&lookupthread, NULL, dundi_precache_thread, st)) {
1051  trans->thread = 0;
1052  ast_log(LOG_WARNING, "Unable to create thread!\n");
1053  ast_free(st);
1054  memset(&ied, 0, sizeof(ied));
1055  dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of threads");
1056  dundi_send(trans, DUNDI_COMMAND_PRECACHERP, 0, 1, &ied);
1057  return -1;
1058  }
1059  } else {
1060  ast_log(LOG_WARNING, "Out of memory!\n");
1061  memset(&ied, 0, sizeof(ied));
1062  dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of memory");
1063  dundi_send(trans, DUNDI_COMMAND_PRECACHERP, 0, 1, &ied);
1064  return -1;
1065  }
1066  return 0;
1067 }
static float dr[4]
Definition: tdd.c:59
struct dundi_mapping::@317 list
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:283
char called_number[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:537
struct dundi_request * parent
Definition: pbx_dundi.c:259
int weight
Definition: dundi.h:227
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:422
static int dundi_cache_time
Definition: pbx_dundi.c:187
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Definition: netsock.c:222
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:371
#define LOG_WARNING
Definition: logger.h:144
dundi_eid * eids[DUNDI_MAX_STACK+1]
Definition: pbx_dundi.c:533
struct dundi_mapping * maps
Definition: pbx_dundi.c:538
struct dundi_transaction * trans
Definition: pbx_dundi.c:541
#define DUNDI_IE_CAUSE
Definition: dundi.h:191
#define MAX_RESULTS
Definition: pbx_dundi.c:145
struct dundi_result * dr
Definition: pbx_dundi.c:269
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:3062
int eid_direct[DUNDI_MAX_STACK+1]
Definition: dundi-parser.h:23
char * called_number
Definition: dundi-parser.h:27
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:265
dundi_eid * eids[DUNDI_MAX_STACK+1]
Definition: dundi-parser.h:22
dundi_eid them_eid
Definition: pbx_dundi.c:242
An Entity ID is essentially a MAC address, brief and unique.
Definition: utils.h:808
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
Definition: netsock.c:320
struct dundi_mapping * next
Definition: pbx_dundi.c:291
int eidcount
Definition: dundi-parser.h:25
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
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:846
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:266
int dundi_ie_append_cause(struct dundi_ie_data *ied, unsigned char ie, unsigned char cause, char *data)
Definition: dundi-parser.c:499
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int techint
Definition: dundi.h:229
int anscount
Definition: dundi-parser.h:30
#define LOG_NOTICE
Definition: logger.h:133
#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:97
int directs[DUNDI_MAX_STACK+1]
Definition: pbx_dundi.c:534
static void * dundi_precache_thread(void *data)
Definition: pbx_dundi.c:703
struct dundi_hint_metadata * hmd
Definition: pbx_dundi.c:271
unsigned int flags
Definition: dundi.h:226
#define DUNDI_COMMAND_PRECACHERP
Definition: dundi.h:165
#define ast_calloc(a, b)
Definition: astmm.h:82
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
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:881
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:536
static int dundi_query ( struct dundi_transaction trans)
static

Definition at line 3256 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().

3257 {
3258  struct dundi_ie_data ied;
3259  int x;
3260  if (!trans->parent) {
3261  ast_log(LOG_WARNING, "Tried to query a transaction with no parent?!?\n");
3262  return -1;
3263  }
3264  memset(&ied, 0, sizeof(ied));
3266  if (!dundi_eid_zero(&trans->us_eid))
3267  dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid);
3268  for (x=0;x<trans->eidcount;x++)
3269  dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->eids[x]);
3272  dundi_ie_append_short(&ied, DUNDI_IE_TTL, trans->ttl);
3273  if (trans->autokilltimeout)
3274  trans->autokillid = ast_sched_add(sched, trans->autokilltimeout, do_autokill, trans);
3275  return dundi_send(trans, DUNDI_COMMAND_EIDQUERY, 0, 0, &ied);
3276 }
struct dundi_request * parent
Definition: pbx_dundi.c:259
int dundi_ie_append_eid(struct dundi_ie_data *ied, unsigned char ie, dundi_eid *eid)
Definition: dundi-parser.c:610
int ast_sched_add(struct sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
Adds a scheduled event Schedule an event to take place at some point in the future. callback will be called with data as the argument, when milliseconds into the future (approximately) If callback returns 0, no further events will be re-scheduled.
Definition: sched.c:446
dundi_eid eids[DUNDI_MAX_STACK+1]
Definition: pbx_dundi.c:239
#define LOG_WARNING
Definition: logger.h:144
Definition: sched.c:57
#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:3062
dundi_eid us_eid
Definition: pbx_dundi.c:241
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:265
#define DUNDI_IE_VERSION
Definition: dundi.h:188
dundi_eid query_eid
Definition: pbx_dundi.c:267
#define DUNDI_IE_EID
Definition: dundi.h:182
static int do_autokill(const void *data)
Definition: pbx_dundi.c:3133
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
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#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 dundi_eid_zero(dundi_eid *eid)
Definition: dundi-parser.c:83
#define DUNDI_COMMAND_EIDQUERY
Definition: dundi.h:162
#define DUNDI_IE_TTL
Definition: dundi.h:187
int dundi_query_eid ( struct dundi_entity_info dei,
const char *  dcontext,
dundi_eid  eid 
)

Retrieve information on a specific EID.

Definition at line 3874 of file pbx_dundi.c.

References dundi_query_eid_internal().

Referenced by dundi_do_query().

3875 {
3876  dundi_eid *avoid[1] = { NULL, };
3877  struct dundi_hint_metadata hmd;
3878  memset(&hmd, 0, sizeof(hmd));
3879  return dundi_query_eid_internal(dei, dcontext, &eid, &hmd, dundi_ttl, 0, avoid);
3880 }
An Entity ID is essentially a MAC address, brief and unique.
Definition: utils.h:808
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:3827
static int dundi_ttl
Definition: pbx_dundi.c:185
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 3827 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, 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_query_eid(), and dundi_query_thread().

3828 {
3829  int res;
3830  struct dundi_request dr;
3831  dundi_eid *rooteid=NULL;
3832  int x;
3833  int ttlms;
3834  int skipped=0;
3835  int foundcache=0;
3836  struct timeval start;
3837 
3838  ttlms = DUNDI_FLUFF_TIME + ttl * DUNDI_TTL_TIME;
3839 
3840  for (x=0;avoid[x];x++)
3841  rooteid = avoid[x];
3842  /* Now perform real check */
3843  memset(&dr, 0, sizeof(dr));
3844  dr.hmd = hmd;
3845  dr.dei = dei;
3846  dr.pfds[0] = dr.pfds[1] = -1;
3847  ast_copy_string(dr.dcontext, dcontext ? dcontext : "e164", sizeof(dr.dcontext));
3848  memcpy(&dr.query_eid, eid, sizeof(dr.query_eid));
3849  if (rooteid)
3850  dr.root_eid = *rooteid;
3851  /* Create transactions */
3852  build_transactions(&dr, ttl, 9999, &foundcache, &skipped, blockempty, 0, 0, NULL, avoid, NULL);
3853 
3854  /* If no TTL, abort and return 0 now after setting TTL expired hint. Couldn't
3855  do this earlier because we didn't know if we were going to have transactions
3856  or not. */
3857  if (!ttl) {
3859  return 0;
3860  }
3861 
3862  /* Optimize transactions */
3863  optimize_transactions(&dr, 9999);
3864  /* Actually perform transactions */
3866  /* Wait for transaction to come back */
3867  start = ast_tvnow();
3868  while (!AST_LIST_EMPTY(&dr.trans) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms))
3869  usleep(1);
3870  res = dr.respcount;
3871  return res;
3872 }
static float dr[4]
Definition: tdd.c:59
#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:142
#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:90
An Entity ID is essentially a MAC address, brief and unique.
Definition: utils.h:808
static int query_transactions(struct dundi_request *dr)
Definition: pbx_dundi.c:3324
#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:223
#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:3337
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:3452
static int dundi_query_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)
static

Definition at line 3968 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, dundi_result_datastore::num_results, OPT_BYPASS_CACHE, parse(), dundi_result_datastore::results, and sort_results().

3969 {
3973  AST_APP_ARG(options);
3974  );
3975  struct ast_flags opts = { 0, };
3976  char *parse;
3977  struct dundi_result_datastore *drds;
3978  struct ast_datastore *datastore;
3979 
3980  if (ast_strlen_zero(data)) {
3981  ast_log(LOG_WARNING, "DUNDIQUERY requires an argument (number)\n");
3982  return -1;
3983  }
3984 
3985  if (!chan) {
3986  ast_log(LOG_ERROR, "DUNDIQUERY can not be used without a channel!\n");
3987  return -1;
3988  }
3989 
3990  parse = ast_strdupa(data);
3991 
3992  AST_STANDARD_APP_ARGS(args, parse);
3993 
3994  if (!ast_strlen_zero(args.options))
3995  ast_app_parse_options(dundi_query_opts, &opts, NULL, args.options);
3996 
3997  if (ast_strlen_zero(args.context))
3998  args.context = "e164";
3999 
4000  if (!(drds = ast_calloc(1, sizeof(*drds)))) {
4001  return -1;
4002  }
4003 
4004  drds->id = ast_atomic_fetchadd_int((int *) &dundi_result_id, 1);
4005  snprintf(buf, len, "%u", drds->id);
4006 
4007  if (!(datastore = ast_datastore_alloc(&dundi_result_datastore_info, buf))) {
4008  drds_destroy(drds);
4009  return -1;
4010  }
4011 
4012  datastore->data = drds;
4013 
4014  drds->num_results = dundi_lookup(drds->results, ARRAY_LEN(drds->results), NULL, args.context,
4015  args.number, ast_test_flag(&opts, OPT_BYPASS_CACHE));
4016 
4017  if (drds->num_results > 0)
4018  sort_results(drds->results, drds->num_results);
4019 
4020  ast_channel_lock(chan);
4021  ast_channel_datastore_add(chan, datastore);
4022  ast_channel_unlock(chan);
4023 
4024  return 0;
4025 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static void sort_results(struct dundi_result *results, int count)
Definition: pbx_dundi.c:2415
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define LOG_WARNING
Definition: logger.h:144
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: app.c:2101
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
Structure for a data store object.
Definition: datastore.h:54
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
Definition: lock.h:603
Number structure.
Definition: app_followme.c:109
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
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 unspec...
Definition: pbx_dundi.c:3678
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
static unsigned int dundi_result_id
Definition: pbx_dundi.c:3944
#define LOG_ERROR
Definition: logger.h:155
static struct @350 args
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
struct ast_datastore * ast_datastore_alloc(const struct ast_datastore_info *info, const char *uid)
Definition: datastore.c:98
#define ast_channel_unlock(chan)
Definition: channel.h:2467
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
unsigned int num_results
Definition: pbx_dundi.c:3948
Structure used to handle boolean flags.
Definition: utils.h:200
void * data
Definition: datastore.h:56
#define ast_calloc(a, b)
Definition: astmm.h:82
struct dundi_result results[MAX_RESULTS]
Definition: pbx_dundi.c:3947
static struct ast_app_option dundi_query_opts[128]
Definition: pbx_dundi.c:3888
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static struct ast_datastore_info dundi_result_datastore_info
Definition: pbx_dundi.c:3963
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2590
static void drds_destroy(struct dundi_result_datastore *drds)
Definition: pbx_dundi.c:3952
static void* dundi_query_thread ( void *  data)
static

Definition at line 736 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, 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().

737 {
738  struct dundi_query_state *st = data;
739  struct dundi_entity_info dei;
740  struct dundi_ie_data ied;
741  struct dundi_hint_metadata hmd;
742  char eid_str[20];
743  int res;
744 
745  ast_debug(1, "Whee, looking up '%s@%s' for '%s'\n", st->called_number, st->called_context,
746  st->eids[0] ? ast_eid_to_str(eid_str, sizeof(eid_str), st->eids[0]) : "ourselves");
747  memset(&ied, 0, sizeof(ied));
748  memset(&dei, 0, sizeof(dei));
749  memset(&hmd, 0, sizeof(hmd));
750  if (!ast_eid_cmp(&st->trans->us_eid, &st->reqeid)) {
751  /* Ooh, it's us! */
752  ast_debug(1, "Neat, someone look for us!\n");
753  ast_copy_string(dei.orgunit, dept, sizeof(dei.orgunit));
754  ast_copy_string(dei.org, org, sizeof(dei.org));
755  ast_copy_string(dei.locality, locality, sizeof(dei.locality));
756  ast_copy_string(dei.stateprov, stateprov, sizeof(dei.stateprov));
757  ast_copy_string(dei.country, country, sizeof(dei.country));
758  ast_copy_string(dei.email, email, sizeof(dei.email));
759  ast_copy_string(dei.phone, phone, sizeof(dei.phone));
760  res = 1;
761  } else {
762  /* If we do not have a canonical result, keep looking */
763  res = dundi_query_eid_internal(&dei, st->called_context, &st->reqeid, &hmd, st->ttl, 1, st->eids);
764  }
766  if (ast_test_flag(st->trans, FLAG_DEAD)) {
767  ast_debug(1, "Our transaction went away!\n");
768  st->trans->thread = 0;
769  destroy_trans(st->trans, 0);
770  } else {
771  if (res) {
772  dundi_ie_append_str(&ied, DUNDI_IE_DEPARTMENT, dei.orgunit);
774  dundi_ie_append_str(&ied, DUNDI_IE_LOCALITY, dei.locality);
775  dundi_ie_append_str(&ied, DUNDI_IE_STATE_PROV, dei.stateprov);
776  dundi_ie_append_str(&ied, DUNDI_IE_COUNTRY, dei.country);
777  dundi_ie_append_str(&ied, DUNDI_IE_EMAIL, dei.email);
778  dundi_ie_append_str(&ied, DUNDI_IE_PHONE, dei.phone);
779  if (!ast_strlen_zero(dei.ipaddr))
780  dundi_ie_append_str(&ied, DUNDI_IE_IPADDR, dei.ipaddr);
781  }
782  dundi_ie_append_hint(&ied, DUNDI_IE_HINT, hmd.flags, hmd.exten);
783  dundi_send(st->trans, DUNDI_COMMAND_EIDRESPONSE, 0, 1, &ied);
784  st->trans->thread = 0;
785  }
787  ast_free(st);
788  return NULL;
789 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
char called_number[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:537
static char locality[80]
Definition: pbx_dundi.c:194
#define DUNDI_IE_IPADDR
Definition: dundi.h:206
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Definition: netsock.c:222
#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:533
struct dundi_transaction * trans
Definition: pbx_dundi.c:541
static char email[80]
Definition: pbx_dundi.c:197
static char phone[80]
Definition: pbx_dundi.c:198
#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:3062
dundi_eid reqeid
Definition: pbx_dundi.c:535
int dundi_ie_append_hint(struct dundi_ie_data *ied, unsigned char ie, unsigned short flags, char *data)
Definition: dundi-parser.c:518
dundi_eid us_eid
Definition: pbx_dundi.c:241
static void destroy_trans(struct dundi_transaction *trans, int fromtimeout)
Definition: pbx_dundi.c:2956
#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: netsock.c:320
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#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:3827
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#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:196
#define DUNDI_IE_ORGANIZATION
Definition: dundi.h:200
#define DUNDI_IE_HINT
Definition: dundi.h:197
#define ast_free(a)
Definition: astmm.h:97
#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:223
static char org[80]
Definition: pbx_dundi.c:193
#define DUNDI_IE_COUNTRY
Definition: dundi.h:203
char called_context[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:536
static char dept[80]
Definition: pbx_dundi.c:192
static char stateprov[80]
Definition: pbx_dundi.c:195
static void dundi_reject ( struct dundi_hdr h,
struct sockaddr_in *  sin 
)
static

Definition at line 444 of file pbx_dundi.c.

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

Referenced by handle_frame().

445 {
446  struct {
447  struct dundi_packet pack;
448  struct dundi_hdr hdr;
449  } tmp;
450  struct dundi_transaction trans;
451  /* Never respond to an INVALID with another INVALID */
452  if (h->cmdresp == DUNDI_COMMAND_INVALID)
453  return;
454  memset(&tmp, 0, sizeof(tmp));
455  memset(&trans, 0, sizeof(trans));
456  memcpy(&trans.addr, sin, sizeof(trans.addr));
457  tmp.hdr.strans = h->dtrans;
458  tmp.hdr.dtrans = h->strans;
459  tmp.hdr.iseqno = h->oseqno;
460  tmp.hdr.oseqno = h->iseqno;
461  tmp.hdr.cmdresp = DUNDI_COMMAND_INVALID;
462  tmp.hdr.cmdflags = 0;
463  tmp.pack.h = (struct dundi_hdr *)tmp.pack.data;
464  tmp.pack.datalen = sizeof(struct dundi_hdr);
465  tmp.pack.parent = &trans;
466  dundi_xmit(&tmp.pack);
467 }
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:2931
static int dundi_result_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)
static

Definition at line 4032 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.

4033 {
4035  AST_APP_ARG(id);
4036  AST_APP_ARG(resultnum);
4037  );
4038  char *parse;
4039  unsigned int num;
4040  struct dundi_result_datastore *drds;
4041  struct ast_datastore *datastore;
4042  int res = -1;
4043 
4044  if (ast_strlen_zero(data)) {
4045  ast_log(LOG_WARNING, "DUNDIRESULT requires an argument (id and resultnum)\n");
4046  goto finish;
4047  }
4048 
4049  if (!chan) {
4050  ast_log(LOG_ERROR, "DUNDRESULT can not be used without a channel!\n");
4051  goto finish;
4052  }
4053 
4054  parse = ast_strdupa(data);
4055 
4056  AST_STANDARD_APP_ARGS(args, parse);
4057 
4058  if (ast_strlen_zero(args.id)) {
4059  ast_log(LOG_ERROR, "A result ID must be provided to DUNDIRESULT\n");
4060  goto finish;
4061  }
4062 
4063  if (ast_strlen_zero(args.resultnum)) {
4064  ast_log(LOG_ERROR, "A result number must be given to DUNDIRESULT!\n");
4065  goto finish;
4066  }
4067 
4068  ast_channel_lock(chan);
4070  ast_channel_unlock(chan);
4071 
4072  if (!datastore) {
4073  ast_log(LOG_WARNING, "No DUNDi results found for query ID '%s'\n", args.id);
4074  goto finish;
4075  }
4076 
4077  drds = datastore->data;
4078 
4079  if (!strcasecmp(args.resultnum, "getnum")) {
4080  snprintf(buf, len, "%u", drds->num_results);
4081  res = 0;
4082  goto finish;
4083  }
4084 
4085  if (sscanf(args.resultnum, "%30u", &num) != 1) {
4086  ast_log(LOG_ERROR, "Invalid value '%s' for resultnum to DUNDIRESULT!\n",
4087  args.resultnum);
4088  goto finish;
4089  }
4090 
4091  if (num && num <= drds->num_results) {
4092  snprintf(buf, len, "%s/%s", drds->results[num - 1].tech, drds->results[num - 1].dest);
4093  res = 0;
4094  } else
4095  ast_log(LOG_WARNING, "Result number %u is not valid for DUNDi query results for ID %s!\n", num, args.id);
4096 
4097 finish:
4098  return res;
4099 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
#define LOG_WARNING
Definition: logger.h:144
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
char dest[256]
Definition: dundi.h:233
Structure for a data store object.
Definition: datastore.h:54
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:2604
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char tech[10]
Definition: dundi.h:232
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
#define LOG_ERROR
Definition: logger.h:155
static struct @350 args
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_channel_unlock(chan)
Definition: channel.h:2467
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
unsigned int num_results
Definition: pbx_dundi.c:3948
void * data
Definition: datastore.h:56
struct dundi_result results[MAX_RESULTS]
Definition: pbx_dundi.c:3947
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
static struct ast_datastore_info dundi_result_datastore_info
Definition: pbx_dundi.c:3963
static int dundi_rexmit ( const void *  data)
static

Definition at line 3039 of file pbx_dundi.c.

References dundi_transaction::addr, ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), 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().

3040 {
3041  struct dundi_packet *pack = (struct dundi_packet *)data;
3042  int res;
3043  AST_LIST_LOCK(&peers);
3044  if (pack->retrans < 1) {
3045  pack->retransid = -1;
3046  if (!ast_test_flag(pack->parent, FLAG_ISQUAL))
3047  ast_log(LOG_NOTICE, "Max retries exceeded to host '%s:%d' msg %d on call %d\n",
3048  ast_inet_ntoa(pack->parent->addr.sin_addr),
3049  ntohs(pack->parent->addr.sin_port), pack->h->oseqno, ntohs(pack->h->strans));
3050  destroy_trans(pack->parent, 1);
3051  res = 0;
3052  } else {
3053  /* Decrement retransmission, try again */
3054  pack->retrans--;
3055  dundi_xmit(pack);
3056  res = 1;
3057  }
3059  return res;
3060 }
#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:2956
unsigned char data[0]
Definition: pbx_dundi.c:219
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: utils.c:564
unsigned short strans
Definition: dundi.h:35
struct sockaddr_in addr
Definition: pbx_dundi.c:237
struct dundi_transaction * parent
Definition: pbx_dundi.c:216
struct dundi_hdr * h
Definition: pbx_dundi.c:214
static int dundi_xmit(struct dundi_packet *pack)
Definition: pbx_dundi.c:2931
static int dundi_send ( struct dundi_transaction trans,
int  cmdresp,
int  flags,
int  final,
struct dundi_ie_data ied 
)
static

Definition at line 3062 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(), 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(), handle_command_response(), precache_trans(), and qualify_peer().

3063 {
3064  struct dundi_packet *pack;
3065  int res;
3066  int len;
3067  char eid_str[20];
3068  len = sizeof(struct dundi_packet) + sizeof(struct dundi_hdr) + (ied ? ied->pos : 0);
3069  /* Reserve enough space for encryption */
3070  if (ast_test_flag(trans, FLAG_ENCRYPT))
3071  len += 384;
3072  pack = ast_calloc(1, len);
3073  if (pack) {
3074  pack->h = (struct dundi_hdr *)(pack->data);
3075  if (cmdresp != DUNDI_COMMAND_ACK) {
3076  pack->retransid = ast_sched_add(sched, trans->retranstimer, dundi_rexmit, pack);
3077  pack->retrans = DUNDI_DEFAULT_RETRANS - 1;
3078  AST_LIST_INSERT_HEAD(&trans->packets, pack, list);
3079  }
3080  pack->parent = trans;
3081  pack->h->strans = htons(trans->strans);
3082  pack->h->dtrans = htons(trans->dtrans);
3083  pack->h->iseqno = trans->iseqno;
3084  pack->h->oseqno = trans->oseqno;
3085  pack->h->cmdresp = cmdresp;
3086  pack->datalen = sizeof(struct dundi_hdr);
3087  if (ied) {
3088  memcpy(pack->h->ies, ied->buf, ied->pos);
3089  pack->datalen += ied->pos;
3090  }
3091  if (final) {
3092  pack->h->cmdresp |= DUNDI_COMMAND_FINAL;
3093  ast_set_flag(trans, FLAG_FINAL);
3094  }
3095  pack->h->cmdflags = flags;
3096  if (cmdresp != DUNDI_COMMAND_ACK) {
3097  trans->oseqno++;
3098  trans->oseqno = trans->oseqno % 256;
3099  }
3100  trans->aseqno = trans->iseqno;
3101  /* If we have their public key, encrypt */
3102  if (ast_test_flag(trans, FLAG_ENCRYPT)) {
3103  switch(cmdresp) {
3104  case DUNDI_COMMAND_REGREQ:
3112  if (dundidebug)
3113  dundi_showframe(pack->h, 2, &trans->addr, pack->datalen - sizeof(struct dundi_hdr));
3114  res = dundi_encrypt(trans, pack);
3115  break;
3116  default:
3117  res = 0;
3118  }
3119  } else
3120  res = 0;
3121  if (!res)
3122  res = dundi_xmit(pack);
3123  if (res)
3124  ast_log(LOG_NOTICE, "Failed to send packet to '%s'\n", ast_eid_to_str(eid_str, sizeof(eid_str), &trans->them_eid));
3125 
3126  if (cmdresp == DUNDI_COMMAND_ACK)
3127  ast_free(pack);
3128  return res;
3129  }
3130  return -1;
3131 }
#define DUNDI_DEFAULT_RETRANS
Definition: dundi.h:214
unsigned char aseqno
Definition: pbx_dundi.c:256
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Definition: netsock.c:222
#define ast_test_flag(p, flag)
Definition: utils.h:63
int ast_sched_add(struct sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
Adds a scheduled event Schedule an event to take place at some point in the future. callback will be called with data as the argument, when milliseconds into the future (approximately) If callback returns 0, no further events will be re-scheduled.
Definition: sched.c:446
#define ast_set_flag(p, flag)
Definition: utils.h:70
Definition: sched.c:57
unsigned char cmdresp
Definition: dundi.h:39
unsigned char oseqno
Definition: dundi.h:38
dundi_eid them_eid
Definition: pbx_dundi.c:242
#define DUNDI_COMMAND_ACK
Definition: dundi.h:159
unsigned char data[0]
Definition: pbx_dundi.c:219
unsigned char buf[8192]
Definition: dundi-parser.h:56
#define DUNDI_COMMAND_DPRESPONSE
Definition: dundi.h:161
static int dundidebug
Definition: pbx_dundi.c:183
unsigned char cmdflags
Definition: dundi.h:40
struct dundi_transaction::packetlist packets
void dundi_showframe(struct dundi_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen)
Definition: dundi-parser.c:433
unsigned char ies[0]
Definition: dundi.h:41
unsigned short strans
Definition: pbx_dundi.c:251
static int dundi_rexmit(const void *data)
Definition: pbx_dundi.c:3039
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
unsigned char oseqno
Definition: pbx_dundi.c:255
#define LOG_NOTICE
Definition: logger.h:133
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:696
unsigned short dtrans
Definition: pbx_dundi.c:252
#define ast_free(a)
Definition: astmm.h:97
unsigned short strans
Definition: dundi.h:35
struct sockaddr_in addr
Definition: pbx_dundi.c:237
if(yyss+yystacksize-1<=yyssp)
Definition: ast_expr2.c:1874
#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:1406
#define ast_calloc(a, b)
Definition: astmm.h:82
#define DUNDI_COMMAND_EIDQUERY
Definition: dundi.h:162
struct dundi_packet::@311 list
#define DUNDI_COMMAND_DPDISCOVER
Definition: dundi.h:160
unsigned short dtrans
Definition: dundi.h:36
unsigned char iseqno
Definition: pbx_dundi.c:253
struct dundi_transaction * parent
Definition: pbx_dundi.c:216
struct dundi_hdr * h
Definition: pbx_dundi.c:214
#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:2931
static char* dundi_set_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 2269 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, and ast_cli_entry::usage.

2270 {
2271  switch (cmd) {
2272  case CLI_INIT:
2273  e->command = "dundi set debug {on|off}";
2274  e->usage =
2275  "Usage: dundi set debug {on|off}\n"
2276  " Enables/Disables dumping of DUNDi packets for debugging purposes\n";
2277  return NULL;
2278  case CLI_GENERATE:
2279  return NULL;
2280  }
2281 
2282  if (a->argc != e->args)
2283  return CLI_SHOWUSAGE;
2284 
2285  if (!strncasecmp(a->argv[e->args -1], "on", 2)) {
2286  dundidebug = 1;
2287  ast_cli(a->fd, "DUNDi Debugging Enabled\n");
2288  } else {
2289  dundidebug = 0;
2290  ast_cli(a->fd, "DUNDi Debugging Disabled\n");
2291  }
2292  return CLI_SUCCESS;
2293 }
const int argc
Definition: cli.h:154
Definition: cli.h:146
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
int args
This gets set in ast_cli_register()
Definition: cli.h:179
const int fd
Definition: cli.h:153
static int dundidebug
Definition: pbx_dundi.c:183
const char *const * argv
Definition: cli.h:155
#define CLI_SHOWUSAGE
Definition: cli.h:44
char * command
Definition: cli.h:180
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
static char* dundi_show_entityid ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 2760 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, and ast_cli_entry::usage.

2761 {
2762  char eid_str[20];
2763  switch (cmd) {
2764  case CLI_INIT:
2765  e->command = "dundi show entityid";
2766  e->usage =
2767  "Usage: dundi show entityid\n"
2768  " Displays the global entityid for this host.\n";
2769  return NULL;
2770  case CLI_GENERATE:
2771  return NULL;
2772  }
2773  if (a->argc != 3)
2774  return CLI_SHOWUSAGE;
2775  AST_LIST_LOCK(&peers);
2776  ast_eid_to_str(eid_str, sizeof(eid_str), &global_eid);
2778  ast_cli(a->fd, "Global EID for this system is '%s'\n", eid_str);
2779  return CLI_SUCCESS;
2780 }
#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)
Definition: netsock.c:222
static dundi_eid global_eid
Definition: pbx_dundi.c:189
const int argc
Definition: cli.h:154
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
Definition: cli.h:146
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
const int fd
Definition: cli.h:153
#define CLI_SHOWUSAGE
Definition: cli.h:44
char * command
Definition: cli.h:180
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
static char* dundi_show_mappings ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 2814 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, map, dundi_mapping::options, dundi_mapping::tech, tech2str(), and ast_cli_entry::usage.

2815 {
2816 #define FORMAT2 "%-12.12s %-7.7s %-12.12s %-10.10s %-5.5s %-25.25s\n"
2817 #define FORMAT "%-12.12s %-7s %-12.12s %-10.10s %-5.5s %-25.25s\n"
2818  struct dundi_mapping *map;
2819  char fs[256];
2820  char weight[8];
2821  switch (cmd) {
2822  case CLI_INIT:
2823  e->command = "dundi show mappings";
2824  e->usage =
2825  "Usage: dundi show mappings\n"
2826  " Lists all known DUNDi mappings.\n";
2827  return NULL;
2828  case CLI_GENERATE:
2829  return NULL;
2830  }
2831  if (a->argc != 3)
2832  return CLI_SHOWUSAGE;
2833  AST_LIST_LOCK(&peers);
2834  ast_cli(a->fd, FORMAT2, "DUNDi Cntxt", "Weight", "Local Cntxt", "Options", "Tech", "Destination");
2835  AST_LIST_TRAVERSE(&mappings, map, list) {
2836  snprintf(weight, sizeof(weight), "%d", get_mapping_weight(map));
2837  ast_cli(a->fd, FORMAT, map->dcontext, weight,
2838  ast_strlen_zero(map->lcontext) ? "<none>" : map->lcontext,
2839  dundi_flags2str(fs, sizeof(fs), map->options), tech2str(map->tech), map->dest);
2840  }
2842  return CLI_SUCCESS;
2843 #undef FORMAT
2844 #undef FORMAT2
2845 }
struct dundi_mapping::@317 list
char dest[512]
Definition: pbx_dundi.c:290
#define FORMAT
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
static int get_mapping_weight(struct dundi_mapping *map)
Definition: pbx_dundi.c:548
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:283
char lcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:284
static int * map
Definition: misdn_config.c:434
static char * tech2str(int tech)
Definition: pbx_dundi.c:371
const int argc
Definition: cli.h:154
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
Definition: cli.h:146
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
const int fd
Definition: cli.h:153
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define CLI_SHOWUSAGE
Definition: cli.h:44
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
char * command
Definition: cli.h:180
#define FORMAT2
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
char * dundi_flags2str(char *buf, int bufsiz, int flags)
Definition: dundi-parser.c:247
static char* dundi_show_peer ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 2561 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_inet_ntoa(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, 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_TIMING_HISTORY, dundi_peer::dynamic, dundi_peer::eid, ast_cli_args::fd, dundi_peer::include, dundi_peer::inkey, ast_cli_args::line, dundi_peer::lookups, dundi_peer::lookuptimes, dundi_peer::model, model2str(), ast_cli_args::n, permission::name, 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.

2562 {
2563  struct dundi_peer *peer;
2564  struct permission *p;
2565  char *order;
2566  char eid_str[20];
2567  int x, cnt;
2568  switch (cmd) {
2569  case CLI_INIT:
2570  e->command = "dundi show peer";
2571  e->usage =
2572  "Usage: dundi show peer [peer]\n"
2573  " Provide a detailed description of a specifid DUNDi peer.\n";
2574  return NULL;
2575  case CLI_GENERATE:
2576  return complete_peer_helper(a->line, a->word, a->pos, a->n, 3);
2577  }
2578  if (a->argc != 4)
2579  return CLI_SHOWUSAGE;
2580  AST_LIST_LOCK(&peers);
2581  AST_LIST_TRAVERSE(&peers, peer, list) {
2582  if (!strcasecmp(ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), a->argv[3]))
2583  break;
2584  }
2585  if (peer) {
2586  switch(peer->order) {
2587  case 0:
2588  order = "Primary";
2589  break;
2590  case 1:
2591  order = "Secondary";
2592  break;
2593  case 2:
2594  order = "Tertiary";
2595  break;
2596  case 3:
2597  order = "Quartiary";
2598  break;
2599  default:
2600  order = "Unknown";
2601  }
2602  ast_cli(a->fd, "Peer: %s\n", ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
2603  ast_cli(a->fd, "Model: %s\n", model2str(peer->model));
2604  ast_cli(a->fd, "Order: %s\n", order);
2605  ast_cli(a->fd, "Host: %s\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "<Unspecified>");
2606  ast_cli(a->fd, "Port: %d\n", ntohs(peer->addr.sin_port));
2607  ast_cli(a->fd, "Dynamic: %s\n", peer->dynamic ? "yes" : "no");
2608  ast_cli(a->fd, "Reg: %s\n", peer->registerid < 0 ? "No" : "Yes");
2609  ast_cli(a->fd, "In Key: %s\n", ast_strlen_zero(peer->inkey) ? "<None>" : peer->inkey);
2610  ast_cli(a->fd, "Out Key: %s\n", ast_strlen_zero(peer->outkey) ? "<None>" : peer->outkey);
2611  if (!AST_LIST_EMPTY(&peer->include))
2612  ast_cli(a->fd, "Include logic%s:\n", peer->model & DUNDI_MODEL_OUTBOUND ? "" : " (IGNORED)");
2613  AST_LIST_TRAVERSE(&peer->include, p, list)
2614  ast_cli(a->fd, "-- %s %s\n", p->allow ? "include" : "do not include", p->name);
2615  if (!AST_LIST_EMPTY(&peer->permit))
2616  ast_cli(a->fd, "Query logic%s:\n", peer->model & DUNDI_MODEL_INBOUND ? "" : " (IGNORED)");
2617  AST_LIST_TRAVERSE(&peer->permit, p, list)
2618  ast_cli(a->fd, "-- %s %s\n", p->allow ? "permit" : "deny", p->name);
2619  cnt = 0;
2620  for (x = 0;x < DUNDI_TIMING_HISTORY; x++) {
2621  if (peer->lookups[x]) {
2622  if (!cnt)
2623  ast_cli(a->fd, "Last few query times:\n");
2624  ast_cli(a->fd, "-- %d. %s (%d ms)\n", x + 1, peer->lookups[x], peer->lookuptimes[x]);
2625  cnt++;
2626  }
2627  }
2628  if (cnt)
2629  ast_cli(a->fd, "Average query time: %d ms\n", peer->avgms);
2630  } else
2631  ast_cli(a->fd, "No such peer '%s'\n", a->argv[3]);
2633  return CLI_SUCCESS;
2634 }
static char * complete_peer_helper(const char *line, const char *word, int pos, int state, int rpos)
Definition: pbx_dundi.c:2381
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
struct sockaddr_in addr
Definition: pbx_dundi.c:296
char * lookups[DUNDI_TIMING_HISTORY]
Definition: pbx_dundi.c:318
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Definition: netsock.c:222
#define DUNDI_TIMING_HISTORY
Definition: pbx_dundi.c:156
const int argc
Definition: cli.h:154
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
Definition: cli.h:146
for(;;)
Definition: ast_expr2.c:2460
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
char outkey[80]
Definition: pbx_dundi.c:301
int lookuptimes[DUNDI_TIMING_HISTORY]
Definition: pbx_dundi.c:317
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
const char * line
Definition: cli.h:156
int registerid
Definition: pbx_dundi.c:303
const int fd
Definition: cli.h:153
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
const int n
Definition: cli.h:159
#define DUNDI_MODEL_INBOUND
Definition: pbx_dundi.c:151
const char *const * argv
Definition: cli.h:155
unsigned int dynamic
Definition: pbx_dundi.c:325
#define CLI_SHOWUSAGE
Definition: cli.h:44
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
static const char name[]
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: utils.c:564
char * command
Definition: cli.h:180
dundi_eid eid
Definition: pbx_dundi.c:295
const char * word
Definition: cli.h:157
char inkey[80]
Definition: pbx_dundi.c:300
if(yyss+yystacksize-1<=yyssp)
Definition: ast_expr2.c:1874
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
struct permissionlist include
Definition: pbx_dundi.c:298
const int pos
Definition: cli.h:158
struct permission::@310 list
#define DUNDI_MODEL_OUTBOUND
Definition: pbx_dundi.c:152
static char * model2str(int model)
Definition: pbx_dundi.c:2367
static char* dundi_show_peers ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 2636 of file pbx_dundi.c.

References dundi_peer::addr, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_eid_to_str(), ast_inet_ntoa(), 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_peer::dynamic, dundi_peer::eid, ast_cli_args::fd, FORMAT, FORMAT2, dundi_peer::lastms, dundi_peer::maxms, dundi_peer::model, model2str(), status, and ast_cli_entry::usage.

2637 {
2638 #define FORMAT2 "%-20.20s %-15.15s %-6.6s %-10.10s %-8.8s %-15.15s\n"
2639 #define FORMAT "%-20.20s %-15.15s %s %-6d %-10.10s %-8.8s %-15.15s\n"
2640  struct dundi_peer *peer;
2641  int registeredonly=0;
2642  char avgms[20];
2643  char eid_str[20];
2644  int online_peers = 0;
2645  int offline_peers = 0;
2646  int unmonitored_peers = 0;
2647  int total_peers = 0;
2648  switch (cmd) {
2649  case CLI_INIT:
2650  e->command = "dundi show peers [registered|include|exclude|begin]";
2651  e->usage =
2652  "Usage: dundi show peers [registered|include|exclude|begin]\n"
2653  " Lists all known DUNDi peers.\n"
2654  " If 'registered' is present, only registered peers are shown.\n";
2655  return NULL;
2656  case CLI_GENERATE:
2657  return NULL;
2658  }
2659 
2660  if ((a->argc != 3) && (a->argc != 4) && (a->argc != 5))
2661  return CLI_SHOWUSAGE;
2662  if ((a->argc == 4)) {
2663  if (!strcasecmp(a->argv[3], "registered")) {
2664  registeredonly = 1;
2665  } else
2666  return CLI_SHOWUSAGE;
2667  }
2668  AST_LIST_LOCK(&peers);
2669  ast_cli(a->fd, FORMAT2, "EID", "Host", "Port", "Model", "AvgTime", "Status");
2670  AST_LIST_TRAVERSE(&peers, peer, list) {
2671  char status[20];
2672  int print_line = -1;
2673  char srch[2000];
2674  total_peers++;
2675  if (registeredonly && !peer->addr.sin_addr.s_addr)
2676  continue;
2677  if (peer->maxms) {
2678  if (peer->lastms < 0) {
2679  strcpy(status, "UNREACHABLE");
2680  offline_peers++;
2681  }
2682  else if (peer->lastms > peer->maxms) {
2683  snprintf(status, sizeof(status), "LAGGED (%d ms)", peer->lastms);
2684  offline_peers++;
2685  }
2686  else if (peer->lastms) {
2687  snprintf(status, sizeof(status), "OK (%d ms)", peer->lastms);
2688  online_peers++;
2689  }
2690  else {
2691  strcpy(status, "UNKNOWN");
2692  offline_peers++;
2693  }
2694  } else {
2695  strcpy(status, "Unmonitored");
2696  unmonitored_peers++;
2697  }
2698  if (peer->avgms)
2699  snprintf(avgms, sizeof(avgms), "%d ms", peer->avgms);
2700  else
2701  strcpy(avgms, "Unavail");
2702  snprintf(srch, sizeof(srch), FORMAT, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid),
2703  peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
2704  peer->dynamic ? "(D)" : "(S)", ntohs(peer->addr.sin_port), model2str(peer->model), avgms, status);
2705 
2706  if (a->argc == 5) {
2707  if (!strcasecmp(a->argv[3],"include") && strstr(srch,a->argv[4])) {
2708  print_line = -1;
2709  } else if (!strcasecmp(a->argv[3],"exclude") && !strstr(srch,a->argv[4])) {
2710  print_line = 1;
2711  } else if (!strcasecmp(a->argv[3],"begin") && !strncasecmp(srch,a->argv[4],strlen(a->argv[4]))) {
2712  print_line = -1;
2713  } else {
2714  print_line = 0;
2715  }
2716  }
2717 
2718  if (print_line) {
2719  ast_cli(a->fd, FORMAT, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid),
2720  peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
2721  peer->dynamic ? "(D)" : "(S)", ntohs(peer->addr.sin_port), model2str(peer->model), avgms, status);
2722  }
2723  }
2724  ast_cli(a->fd, "%d dundi peers [%d online, %d offline, %d unmonitored]\n", total_peers, online_peers, offline_peers, unmonitored_peers);
2726  return CLI_SUCCESS;
2727 #undef FORMAT
2728 #undef FORMAT2
2729 }
#define FORMAT
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
struct sockaddr_in addr
Definition: pbx_dundi.c:296
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Definition: netsock.c:222
const int argc
Definition: cli.h:154
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
Definition: cli.h:146
struct dundi_peer::@318 list
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
int lastms
Definition: pbx_dundi.c:326
const int fd
Definition: cli.h:153
const char *const * argv
Definition: cli.h:155
unsigned int dynamic
Definition: pbx_dundi.c:325
#define CLI_SHOWUSAGE
Definition: cli.h:44
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: utils.c:564
char * command
Definition: cli.h:180
dundi_eid eid
Definition: pbx_dundi.c:295
#define FORMAT2
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
static char * model2str(int model)
Definition: pbx_dundi.c:2367
jack_status_t status
Definition: app_jack.c:143
static char* dundi_show_precache ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 2847 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, dundi_precache_queue::number, and ast_cli_entry::usage.

2848 {
2849 #define FORMAT2 "%-12.12s %-12.12s %-10.10s\n"
2850 #define FORMAT "%-12.12s %-12.12s %02d:%02d:%02d\n"
2851  struct dundi_precache_queue *qe;
2852  int h,m,s;
2853  time_t now;
2854  switch (cmd) {
2855  case CLI_INIT:
2856  e->command = "dundi show precache";
2857  e->usage =
2858  "Usage: dundi show precache\n"
2859  " Lists all known DUNDi scheduled precache updates.\n";
2860  return NULL;
2861  case CLI_GENERATE:
2862  return NULL;
2863  }
2864  if (a->argc != 3)
2865  return CLI_SHOWUSAGE;
2866  time(&now);
2867  ast_cli(a->fd, FORMAT2, "Number", "Context", "Expiration");
2868  AST_LIST_LOCK(&pcq);
2869  AST_LIST_TRAVERSE(&pcq, qe, list) {
2870  s = qe->expiration - now;
2871  h = s / 3600;
2872  s = s % 3600;
2873  m = s / 60;
2874  s = s % 60;
2875  ast_cli(a->fd, FORMAT, qe->number, qe->context, h,m,s);
2876  }
2877  AST_LIST_UNLOCK(&pcq);
2878 
2879  return CLI_SUCCESS;
2880 #undef FORMAT
2881 #undef FORMAT2
2882 }
Definition: pbx_dundi.c:333
#define FORMAT
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
const int argc
Definition: cli.h:154
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
Definition: cli.h:146
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
const int fd
Definition: cli.h:153
struct dundi_precache_queue::@312 list
#define CLI_SHOWUSAGE
Definition: cli.h:44
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
char * command
Definition: cli.h:180
#define FORMAT2
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
static char* dundi_show_requests ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 2782 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, dundi_request::maxcount, dundi_request::number, dundi_request::respcount, dundi_request::root_eid, and ast_cli_entry::usage.

2783 {
2784 #define FORMAT2 "%-15s %-15s %-15s %-3.3s %-3.3s\n"
2785 #define FORMAT "%-15s %-15s %-15s %-3.3d %-3.3d\n"
2786  struct dundi_request *req;
2787  char eidstr[20];
2788  switch (cmd) {
2789  case CLI_INIT:
2790  e->command = "dundi show requests";
2791  e->usage =
2792  "Usage: dundi show requests\n"
2793  " Lists all known pending DUNDi requests.\n";
2794  return NULL;
2795  case CLI_GENERATE:
2796  return NULL;
2797  }
2798  if (a->argc != 3)
2799  return CLI_SHOWUSAGE;
2800  AST_LIST_LOCK(&peers);
2801  ast_cli(a->fd, FORMAT2, "Number", "Context", "Root", "Max", "Rsp");
2802  AST_LIST_TRAVERSE(&requests, req, list) {
2803  ast_cli(a->fd, FORMAT, req->number, req->dcontext,
2804  dundi_eid_zero(&req->root_eid) ? "<unspecified>" : ast_eid_to_str(eidstr, sizeof(eidstr), &req->root_eid), req->maxcount, req->respcount);
2805  }
2807  return CLI_SUCCESS;
2808 #undef FORMAT
2809 #undef FORMAT2
2810 }
#define FORMAT
#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)
Definition: netsock.c:222
struct dundi_request::@316 list
const int argc
Definition: cli.h:154
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
Definition: cli.h:146
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:265
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
const int fd
Definition: cli.h:153
char number[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:266
#define CLI_SHOWUSAGE
Definition: cli.h:44
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
char * command
Definition: cli.h:180
#define FORMAT2
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
dundi_eid root_eid
Definition: pbx_dundi.c:268
int dundi_eid_zero(dundi_eid *eid)
Definition: dundi-parser.c:83
static char* dundi_show_trans ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 2731 of file pbx_dundi.c.

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

2732 {
2733 #define FORMAT2 "%-22.22s %-5.5s %-5.5s %-3.3s %-3.3s %-3.3s\n"
2734 #define FORMAT "%-16.16s:%5d %-5.5d %-5.5d %-3.3d %-3.3d %-3.3d\n"
2735  struct dundi_transaction *trans;
2736  switch (cmd) {
2737  case CLI_INIT:
2738  e->command = "dundi show trans";
2739  e->usage =
2740  "Usage: dundi show trans\n"
2741  " Lists all known DUNDi transactions.\n";
2742  return NULL;
2743  case CLI_GENERATE:
2744  return NULL;
2745  }
2746  if (a->argc != 3)
2747  return CLI_SHOWUSAGE;
2748  AST_LIST_LOCK(&peers);
2749  ast_cli(a->fd, FORMAT2, "Remote", "Src", "Dst", "Tx", "Rx", "Ack");
2750  AST_LIST_TRAVERSE(&alltrans, trans, all) {
2751  ast_cli(a->fd, FORMAT, ast_inet_ntoa(trans->addr.sin_addr),
2752  ntohs(trans->addr.sin_port), trans->strans, trans->dtrans, trans->oseqno, trans->iseqno, trans->aseqno);
2753  }
2755  return CLI_SUCCESS;
2756 #undef FORMAT
2757 #undef FORMAT2
2758 }
#define FORMAT
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
unsigned char aseqno
Definition: pbx_dundi.c:256
const int argc
Definition: cli.h:154
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
Definition: cli.h:146
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
const int fd
Definition: cli.h:153
unsigned short strans
Definition: pbx_dundi.c:251
#define CLI_SHOWUSAGE
Definition: cli.h:44
unsigned char oseqno
Definition: pbx_dundi.c:255
#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:252
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: utils.c:564
char * command
Definition: cli.h:180
struct sockaddr_in addr
Definition: pbx_dundi.c:237
#define FORMAT2
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
struct dundi_transaction::@314 all
unsigned char iseqno
Definition: pbx_dundi.c:253
static char* dundi_store_history ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 2295 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, and ast_cli_entry::usage.

2296 {
2297  switch (cmd) {
2298  case CLI_INIT:
2299  e->command = "dundi store history {on|off}";
2300  e->usage =
2301  "Usage: dundi store history {on|off}\n"
2302  " Enables/Disables storing of DUNDi requests and times for debugging\n"
2303  "purposes\n";
2304  return NULL;
2305  case CLI_GENERATE:
2306  return NULL;
2307  }
2308 
2309  if (a->argc != e->args)
2310  return CLI_SHOWUSAGE;
2311 
2312  if (!strncasecmp(a->argv[e->args -1], "on", 2)) {
2313  global_storehistory = 1;
2314  ast_cli(a->fd, "DUNDi History Storage Enabled\n");
2315  } else {
2316  global_storehistory = 0;
2317  ast_cli(a->fd, "DUNDi History Storage Disabled\n");
2318  }
2319  return CLI_SUCCESS;
2320 }
const int argc
Definition: cli.h:154
Definition: cli.h:146
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
int args
This gets set in ast_cli_register()
Definition: cli.h:179
const int fd
Definition: cli.h:153
static int global_storehistory
Definition: pbx_dundi.c:191
const char *const * argv
Definition: cli.h:155
#define CLI_SHOWUSAGE
Definition: cli.h:44
char * command
Definition: cli.h:180
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
static int dundi_xmit ( struct dundi_packet pack)
static

Definition at line 2931 of file pbx_dundi.c.

References dundi_transaction::addr, ast_inet_ntoa(), ast_log(), 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().

2932 {
2933  int res;
2934  if (dundidebug)
2935  dundi_showframe(pack->h, 0, &pack->parent->addr, pack->datalen - sizeof(struct dundi_hdr));
2936  res = sendto(netsocket, pack->data, pack->datalen, 0, (struct sockaddr *)&pack->parent->addr, sizeof(pack->parent->addr));
2937  if (res < 0) {
2938  ast_log(LOG_WARNING, "Failed to transmit to '%s:%d': %s\n",
2939  ast_inet_ntoa(pack->parent->addr.sin_addr),
2940  ntohs(pack->parent->addr.sin_port), strerror(errno));
2941  }
2942  if (res > 0)
2943  res = 0;
2944  return res;
2945 }
#define LOG_WARNING
Definition: logger.h:144
unsigned char data[0]
Definition: pbx_dundi.c:219
static int netsocket
Definition: pbx_dundi.c:178
static int dundidebug
Definition: pbx_dundi.c:183
void dundi_showframe(struct dundi_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen)
Definition: dundi-parser.c:433
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int errno
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: utils.c:564
struct sockaddr_in addr
Definition: pbx_dundi.c:237
struct dundi_transaction * parent
Definition: pbx_dundi.c:216
struct dundi_hdr * h
Definition: pbx_dundi.c:214
static int dundifunc_read ( struct ast_channel chan,
const char *  cmd,
char *  num,
char *  buf,
size_t  len 
)
static

Definition at line 3890 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, OPT_BYPASS_CACHE, parse(), and sort_results().

3891 {
3892  int results;
3893  int x;
3894  struct dundi_result dr[MAX_RESULTS];
3898  AST_APP_ARG(options);
3899  );
3900  char *parse;
3901  struct ast_flags opts = { 0, };
3902 
3903  buf[0] = '\0';
3904 
3905  if (ast_strlen_zero(num)) {
3906  ast_log(LOG_WARNING, "DUNDILOOKUP requires an argument (number)\n");
3907  return -1;
3908  }
3909 
3910  parse = ast_strdupa(num);
3911 
3912  AST_STANDARD_APP_ARGS(args, parse);
3913 
3914  if (!ast_strlen_zero(args.options)) {
3915  ast_app_parse_options(dundi_query_opts, &opts, NULL, args.options);
3916  }
3917  if (ast_strlen_zero(args.context)) {
3918  args.context = "e164";
3919  }
3920 
3921  results = dundi_lookup(dr, MAX_RESULTS, NULL, args.context, args.number, ast_test_flag(&opts, OPT_BYPASS_CACHE));
3922  if (results > 0) {
3923  sort_results(dr, results);
3924  for (x = 0; x < results; x++) {
3925  if (ast_test_flag(dr + x, DUNDI_FLAG_EXISTS)) {
3926  snprintf(buf, len, "%s/%s", dr[x].tech, dr[x].dest);
3927  break;
3928  }
3929  }
3930  }
3931 
3932  return 0;
3933 }
static float dr[4]
Definition: tdd.c:59
static void sort_results(struct dundi_result *results, int count)
Definition: pbx_dundi.c:2415
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define LOG_WARNING
Definition: logger.h:144
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: app.c:2101
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
#define MAX_RESULTS
Definition: pbx_dundi.c:145
Number structure.
Definition: app_followme.c:109
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
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 unspec...
Definition: pbx_dundi.c:3678
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
static struct @350 args
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
Structure used to handle boolean flags.
Definition: utils.h:200
static struct ast_app_option dundi_query_opts[128]
Definition: pbx_dundi.c:3888
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static int encrypt_memcpy ( unsigned char *  dst,
unsigned char *  src,
int  len,
unsigned char *  iv,
ast_aes_encrypt_key ecx 
)
static

Definition at line 1351 of file pbx_dundi.c.

References ast_aes_encrypt().

Referenced by dundi_encrypt().

1352 {
1353  unsigned char curblock[16];
1354  int x;
1355  memcpy(curblock, iv, sizeof(curblock));
1356  while(len > 0) {
1357  for (x=0;x<16;x++)
1358  curblock[x] ^= src[x];
1359  ast_aes_encrypt(curblock, dst, ecx);
1360  memcpy(curblock, dst, sizeof(curblock));
1361  dst += 16;
1362  src += 16;
1363  len -= 16;
1364  }
1365  return 0;
1366 }
void ast_aes_encrypt(const unsigned char *in, unsigned char *out, const ast_aes_encrypt_key *ctx)
AES encrypt data.
Definition: res_crypto.c:471
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static struct dundi_peer* find_peer ( dundi_eid eid)
static

Definition at line 504 of file pbx_dundi.c.

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

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

505 {
506  struct dundi_peer *cur = NULL;
507 
508  if (!eid)
509  eid = &empty_eid;
510 
511  AST_LIST_TRAVERSE(&peers, cur, list) {
512  if (!ast_eid_cmp(&cur->eid,eid))
513  break;
514  }
515 
516  if (!cur && any_peer)
517  cur = any_peer;
518 
519  return cur;
520 }
struct dundi_peer::@318 list
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
Definition: netsock.c:320
static struct dundi_peer * any_peer
Wildcard peer.
Definition: pbx_dundi.c:343
static dundi_eid empty_eid
Definition: pbx_dundi.c:203
#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:295
static struct dundi_transaction* find_transaction ( struct dundi_hdr hdr,
struct sockaddr_in *  sin 
)
static

Definition at line 402 of file pbx_dundi.c.

References dundi_transaction::addr, AST_LIST_TRAVERSE, 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, inaddrcmp(), dundi_hdr::strans, and dundi_transaction::strans.

Referenced by handle_frame().

403 {
404  struct dundi_transaction *trans;
405 
406  /* Look for an exact match first */
407  AST_LIST_TRAVERSE(&alltrans, trans, all) {
408  if (!inaddrcmp(&trans->addr, sin) &&
409  ((trans->strans == (ntohs(hdr->dtrans) & 32767)) /* Matches our destination */ ||
410  ((trans->dtrans == (ntohs(hdr->strans) & 32767)) && (!hdr->dtrans))) /* We match their destination */) {
411  if (hdr->strans)
412  trans->dtrans = ntohs(hdr->strans) & 32767;
413  return trans;
414  }
415  }
416 
417  switch(hdr->cmdresp & 0x7f) {
422  case DUNDI_COMMAND_NULL:
424  if (!hdr->strans)
425  break;
426  /* Create new transaction */
427  if (!(trans = create_transaction(NULL)))
428  break;
429  memcpy(&trans->addr, sin, sizeof(trans->addr));
430  trans->dtrans = ntohs(hdr->strans) & 32767;
431  default:
432  break;
433  }
434 
435  return trans;
436 }
static force_inline int inaddrcmp(const struct sockaddr_in *sin1, const struct sockaddr_in *sin2)
Compares the source address and port of two sockaddr_in.
Definition: network.h:90
#define DUNDI_COMMAND_ENCRYPT
Definition: dundi.h:172
unsigned char cmdresp
Definition: dundi.h:39
static struct dundi_transaction * create_transaction(struct dundi_peer *p)
Definition: pbx_dundi.c:2900
unsigned short strans
Definition: pbx_dundi.c:251
#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:252
unsigned short strans
Definition: dundi.h:35
struct sockaddr_in addr
Definition: pbx_dundi.c:237
#define DUNDI_COMMAND_PRECACHERQ
Definition: dundi.h:164
#define DUNDI_COMMAND_REGREQ
Definition: dundi.h:169
#define DUNDI_COMMAND_EIDQUERY
Definition: dundi.h:162
struct dundi_transaction::@314 all
#define DUNDI_COMMAND_DPDISCOVER
Definition: dundi.h:160
unsigned short dtrans
Definition: dundi.h:36
#define DUNDI_COMMAND_NULL
Definition: dundi.h:168
static int get_mapping_weight ( struct dundi_mapping map)
static

Definition at line 548 of file pbx_dundi.c.

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

Referenced by dundi_lookup_local(), and dundi_show_mappings().

549 {
550  char buf[32];
551 
552  buf[0] = 0;
553  if (map->weightstr) {
554  pbx_substitute_variables_helper(NULL, map->weightstr, buf, sizeof(buf) - 1);
555  if (sscanf(buf, "%30d", &map->_weight) != 1)
556  map->_weight = MAX_WEIGHT;
557  }
558 
559  return map->_weight;
560 }
void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
Definition: pbx.c:4676
char * weightstr
Definition: pbx_dundi.c:286
#define MAX_WEIGHT
Definition: pbx_dundi.c:149
static int get_trans_id ( void  )
static

Definition at line 469 of file pbx_dundi.c.

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

Referenced by create_transaction(), and reset_transaction().

470 {
471  struct dundi_transaction *t;
472  int stid = (ast_random() % 32766) + 1;
473  int tid = stid;
474 
475  do {
477  if (t->strans == tid)
478  break;
479  }
480  if (!t)
481  return tid;
482  tid = (tid % 32766) + 1;
483  } while (tid != stid);
484 
485  return 0;
486 }
long int ast_random(void)
Definition: utils.c:1640
unsigned short strans
Definition: pbx_dundi.c:251
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct dundi_transaction::@314 all
static int handle_command_response ( struct dundi_transaction trans,
struct dundi_hdr hdr,
int  datalen,
int  encrypted 
)
static

Definition at line 1553 of file pbx_dundi.c.

References dundi_transaction::addr, dundi_peer::addr, dundi_ies::anscount, dundi_ies::answers, any_peer, apply_peer(), dundi_transaction::aseqno, ast_alloca, ast_calloc, ast_clear_flag, ast_clear_flag_nonstd, ast_copy_string(), ast_db_put(), ast_debug, ast_eid_cmp(), ast_eid_to_str(), ast_free, ast_inet_ntoa(), 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_strlen_zero(), ast_test_flag, ast_test_flag_nonstd, ast_verb, cache_save(), cache_save_hint(), dundi_ies::called_context, dundi_ies::called_number, dundi_ies::cause, check_key(), dundi_hdr::cmdresp, dundi_entity_info::country, dundi_answer::data, dundi_hint::data, dundi_request::dcontext, dundi_transaction::dcx, deep_copy_peer(), default_expiration, dundi_request::dei, dundi_result::dest, do_register_expire(), dundi_request::dr, dundi_ack(), dundi_answer_entity(), dundi_answer_query(), dundi_cache_time, DUNDI_CAUSE_GENERAL, DUNDI_CAUSE_NOAUTH, DUNDI_COMMAND_CANCEL, DUNDI_COMMAND_DPDISCOVER, DUNDI_COMMAND_DPRESPONSE, DUNDI_COMMAND_EIDQUERY, DUNDI_COMMAND_EIDRESPONSE, DUNDI_COMMAND_ENCREJ, DUNDI_COMMAND_ENCRYPT, DUNDI_COMMAND_INVALID, DUNDI_COMMAND_NULL, DUNDI_COMMAND_PRECACHERP, DUNDI_COMMAND_PRECACHERQ, DUNDI_COMMAND_REGREQ, DUNDI_COMMAND_REGRESPONSE, DUNDI_COMMAND_UNKNOWN, dundi_decrypt(), dundi_eid_to_str_short(), DUNDI_HINT_DONT_ASK, DUNDI_HINT_TTL_EXPIRED, DUNDI_HINT_UNAFFECTED, dundi_ie_append_byte(), dundi_ie_append_cause(), dundi_ie_append_eid(), dundi_ie_append_encdata(), dundi_ie_append_raw(), dundi_ie_append_short(), DUNDI_IE_CAUSE, DUNDI_IE_EID, DUNDI_IE_ENCDATA, DUNDI_IE_EXPIRATION, DUNDI_IE_SHAREDKEY, DUNDI_IE_SIGNATURE, DUNDI_IE_UNKNOWN, DUNDI_MODEL_INBOUND, dundi_parse_ies(), dundi_prop_precache(), dundi_send(), dundi_showframe(), 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, inaddrcmp(), dundi_peer::include, dundi_peer::inkey, dundi_entity_info::ipaddr, dundi_transaction::iseqno, dundi_encblock::iv, dundi_ies::keycrc32, dundi_transaction::lasttrans, dundi_entity_info::locality, LOG_NOTICE, LOG_WARNING, MAX_PACKET_SIZE, dundi_request::maxcount, dundi_peer::model, 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, 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().

1554 {
1555  /* Handle canonical command / response */
1556  int final = hdr->cmdresp & 0x80;
1557  int cmd = hdr->cmdresp & 0x7f;
1558  int x,y,z;
1559  int resp;
1560  int res;
1561  int authpass=0;
1562  unsigned char *bufcpy;
1563 #ifdef LOW_MEMORY
1564  struct dundi_ie_data *ied = ast_calloc(1, sizeof(*ied));
1565 #else
1566  struct dundi_ie_data _ied = {
1567  .pos = 0,
1568  };
1569  struct dundi_ie_data *ied = &_ied;
1570 #endif
1571  struct dundi_ies ies = {
1572  .eidcount = 0,
1573  };
1574  struct dundi_peer *peer = NULL;
1575  char eid_str[20];
1576  char eid_str2[20];
1577  int retval = -1;
1578 
1579  if (!ied) {
1580  return -1;
1581  }
1582 
1583  if (datalen) {
1584  bufcpy = ast_alloca(datalen);
1585  /* Make a copy for parsing */
1586  memcpy(bufcpy, hdr->ies, datalen);
1587  ast_debug(1, "Got canonical message %d (%d), %d bytes data%s\n", cmd, hdr->oseqno, datalen, final ? " (Final)" : "");
1588  if (dundi_parse_ies(&ies, bufcpy, datalen) < 0) {
1589  ast_log(LOG_WARNING, "Failed to parse DUNDI information elements!\n");
1590  goto return_cleanup;
1591  }
1592  }
1593  switch(cmd) {
1597  if (cmd == DUNDI_COMMAND_EIDQUERY)
1599  else if (cmd == DUNDI_COMMAND_PRECACHERQ)
1600  resp = DUNDI_COMMAND_PRECACHERP;
1601  else
1602  resp = DUNDI_COMMAND_DPRESPONSE;
1603  /* A dialplan or entity discover -- qualify by highest level entity */
1604  peer = find_peer(ies.eids[0]);
1605  if (!peer) {
1607  dundi_send(trans, resp, 0, 1, ied);
1608  } else {
1609  int hasauth = 0;
1610  trans->us_eid = peer->us_eid;
1611  if (strlen(peer->inkey)) {
1612  hasauth = encrypted;
1613  } else
1614  hasauth = 1;
1615  if (hasauth) {
1616  /* Okay we're authentiated and all, now we check if they're authorized */
1617  if (!ies.called_context)
1618  ies.called_context = "e164";
1619  if (cmd == DUNDI_COMMAND_EIDQUERY) {
1620  res = dundi_answer_entity(trans, &ies, ies.called_context);
1621  } else {
1622  if (ast_strlen_zero(ies.called_number)) {
1623  /* They're not permitted to access that context */
1624  dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Invalid or missing number/entity");
1625  dundi_send(trans, resp, 0, 1, ied);
1626  } else if ((cmd == DUNDI_COMMAND_DPDISCOVER) &&
1627  (peer->model & DUNDI_MODEL_INBOUND) &&
1628  has_permission(&peer->permit, ies.called_context)) {
1629  res = dundi_answer_query(trans, &ies, ies.called_context);
1630  if (res < 0) {
1631  /* There is no such dundi context */
1632  dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Unsupported DUNDI Context");
1633  dundi_send(trans, resp, 0, 1, ied);
1634  }
1635  } else if ((cmd = DUNDI_COMMAND_PRECACHERQ) &&
1636  (peer->pcmodel & DUNDI_MODEL_INBOUND) &&
1637  has_permission(&peer->include, ies.called_context)) {
1638  res = dundi_prop_precache(trans, &ies, ies.called_context);
1639  if (res < 0) {
1640  /* There is no such dundi context */
1641  dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Unsupported DUNDI Context");
1642  dundi_send(trans, resp, 0, 1, ied);
1643  }
1644  } else {
1645  /* They're not permitted to access that context */
1646  dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Permission to context denied");
1647  dundi_send(trans, resp, 0, 1, ied);
1648  }
1649  }
1650  } else {
1651  /* They're not permitted to access that context */
1652  dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Unencrypted responses not permitted");
1653  dundi_send(trans, resp, 0, 1, ied);
1654  }
1655  }
1656  break;
1657  case DUNDI_COMMAND_REGREQ:
1658  /* A register request -- should only have one entity */
1659  peer = find_peer(ies.eids[0]);
1660 
1661  /* if the peer is not found and we have a valid 'any_peer' setting */
1662  if (any_peer && peer == any_peer) {
1663  /* copy any_peer into a new peer object */
1664  peer = ast_calloc(1, sizeof(*peer));
1665  if (peer) {
1666  deep_copy_peer(peer, any_peer);
1667 
1668  /* set EID to remote EID */
1669  peer->eid = *ies.eids[0];
1670 
1671  AST_LIST_LOCK(&peers);
1672  AST_LIST_INSERT_HEAD(&peers, peer, list);
1674  }
1675  }
1676 
1677  if (!peer || !peer->dynamic) {
1679  dundi_send(trans, DUNDI_COMMAND_REGRESPONSE, 0, 1, ied);
1680  } else {
1681  int hasauth = 0;
1682  trans->us_eid = peer->us_eid;
1683  if (!ast_strlen_zero(peer->inkey)) {
1684  hasauth = encrypted;
1685  } else
1686  hasauth = 1;
1687  if (hasauth) {
1688  int expire = default_expiration;
1689  char data[256];
1690  int needqual = 0;
1692  peer->registerexpire = ast_sched_add(sched, (expire + 10) * 1000, do_register_expire, peer);
1693  snprintf(data, sizeof(data), "%s:%d:%d", ast_inet_ntoa(trans->addr.sin_addr),
1694  ntohs(trans->addr.sin_port), expire);
1695  ast_db_put("dundi/dpeers", dundi_eid_to_str_short(eid_str, sizeof(eid_str), &peer->eid), data);
1696  if (inaddrcmp(&peer->addr, &trans->addr)) {
1697  ast_verb(3, "Registered DUNDi peer '%s' at '%s:%d'\n",
1698  ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid),
1699  ast_inet_ntoa(trans->addr.sin_addr), ntohs(trans->addr.sin_port));
1700  needqual = 1;
1701  }
1702 
1703  memcpy(&peer->addr, &trans->addr, sizeof(peer->addr));
1705  dundi_send(trans, DUNDI_COMMAND_REGRESPONSE, 0, 1, ied);
1706  if (needqual)
1707  qualify_peer(peer, 1);
1708  }
1709  }
1710  break;
1712  /* A dialplan response, lets see what we got... */
1713  if (ies.cause < 1) {
1714  /* Success of some sort */
1715  ast_debug(1, "Looks like success of some sort (%d), %d answers\n", ies.cause, ies.anscount);
1716  if (ast_test_flag(trans, FLAG_ENCRYPT)) {
1717  authpass = encrypted;
1718  } else
1719  authpass = 1;
1720  if (authpass) {
1721  /* Pass back up answers */
1722  if (trans->parent && trans->parent->dr) {
1723  y = trans->parent->respcount;
1724  for (x=0;x<ies.anscount;x++) {
1725  if (trans->parent->respcount < trans->parent->maxcount) {
1726  /* Make sure it's not already there */
1727  for (z=0;z<trans->parent->respcount;z++) {
1728  if ((trans->parent->dr[z].techint == ies.answers[x]->protocol) &&
1729  !strcmp(trans->parent->dr[z].dest, (char *)ies.answers[x]->data))
1730  break;
1731  }
1732  if (z == trans->parent->respcount) {
1733  /* Copy into parent responses */
1734  trans->parent->dr[trans->parent->respcount].flags = ntohs(ies.answers[x]->flags);
1735  trans->parent->dr[trans->parent->respcount].techint = ies.answers[x]->protocol;
1736  trans->parent->dr[trans->parent->respcount].weight = ntohs(ies.answers[x]->weight);
1737  trans->parent->dr[trans->parent->respcount].eid = ies.answers[x]->eid;
1738  if (ies.expiration > 0)
1739  trans->parent->dr[trans->parent->respcount].expiration = ies.expiration;
1740  else
1741  trans->parent->dr[trans->parent->respcount].expiration = dundi_cache_time;
1742  ast_eid_to_str(trans->parent->dr[trans->parent->respcount].eid_str,
1743  sizeof(trans->parent->dr[trans->parent->respcount].eid_str),
1744  &ies.answers[x]->eid);
1745  ast_copy_string(trans->parent->dr[trans->parent->respcount].dest, (char *)ies.answers[x]->data,
1746  sizeof(trans->parent->dr[trans->parent->respcount].dest));
1747  ast_copy_string(trans->parent->dr[trans->parent->respcount].tech, tech2str(ies.answers[x]->protocol),
1748  sizeof(trans->parent->dr[trans->parent->respcount].tech));
1749  trans->parent->respcount++;
1751  } else if (trans->parent->dr[z].weight > ies.answers[x]->weight) {
1752  /* Update weight if appropriate */
1753  trans->parent->dr[z].weight = ies.answers[x]->weight;
1754  }
1755  } else
1756  ast_log(LOG_NOTICE, "Dropping excessive answers to request for %s@%s\n",
1757  trans->parent->number, trans->parent->dcontext);
1758  }
1759  /* Save all the results (if any) we had. Even if no results, still cache lookup. Let
1760  the cache know if this request was unaffected by our entity list. */
1761  cache_save(&trans->them_eid, trans->parent, y,
1762  ies.hint ? ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_UNAFFECTED)) : 0, ies.expiration, 0);
1763  if (ies.hint) {
1764  cache_save_hint(&trans->them_eid, trans->parent, ies.hint, ies.expiration);
1767  if (ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_DONT_ASK))) {
1768  if (strlen((char *)ies.hint->data) > strlen(trans->parent->hmd->exten)) {
1769  ast_copy_string(trans->parent->hmd->exten, (char *)ies.hint->data,
1770  sizeof(trans->parent->hmd->exten));
1771  }
1772  } else {
1774  }
1775  }
1776  if (ies.expiration > 0) {
1777  if (trans->parent->expiration > ies.expiration) {
1778  trans->parent->expiration = ies.expiration;
1779  }
1780  }
1781  }
1782  /* Close connection if not final */
1783  if (!final)
1784  dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
1785  }
1786 
1787  } else {
1788  /* Auth failure, check for data */
1789  if (!final) {
1790  /* Cancel if they didn't already */
1791  dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
1792  }
1793  }
1794  break;
1796  /* A dialplan response, lets see what we got... */
1797  if (ies.cause < 1) {
1798  /* Success of some sort */
1799  ast_debug(1, "Looks like success of some sort (%d)\n", ies.cause);
1800  if (ast_test_flag(trans, FLAG_ENCRYPT)) {
1801  authpass = encrypted;
1802  } else
1803  authpass = 1;
1804  if (authpass) {
1805  /* Pass back up answers */
1806  if (trans->parent && trans->parent->dei && ies.q_org) {
1807  if (!trans->parent->respcount) {
1808  trans->parent->respcount++;
1809  if (ies.q_dept)
1810  ast_copy_string(trans->parent->dei->orgunit, ies.q_dept, sizeof(trans->parent->dei->orgunit));
1811  if (ies.q_org)
1812  ast_copy_string(trans->parent->dei->org, ies.q_org, sizeof(trans->parent->dei->org));
1813  if (ies.q_locality)
1814  ast_copy_string(trans->parent->dei->locality, ies.q_locality, sizeof(trans->parent->dei->locality));
1815  if (ies.q_stateprov)
1816  ast_copy_string(trans->parent->dei->stateprov, ies.q_stateprov, sizeof(trans->parent->dei->stateprov));
1817  if (ies.q_country)
1818  ast_copy_string(trans->parent->dei->country, ies.q_country, sizeof(trans->parent->dei->country));
1819  if (ies.q_email)
1820  ast_copy_string(trans->parent->dei->email, ies.q_email, sizeof(trans->parent->dei->email));
1821  if (ies.q_phone)
1822  ast_copy_string(trans->parent->dei->phone, ies.q_phone, sizeof(trans->parent->dei->phone));
1823  if (ies.q_ipaddr)
1824  ast_copy_string(trans->parent->dei->ipaddr, ies.q_ipaddr, sizeof(trans->parent->dei->ipaddr));
1825  if (!ast_eid_cmp(&trans->them_eid, &trans->parent->query_eid)) {
1826  /* If it's them, update our address */
1827  ast_copy_string(trans->parent->dei->ipaddr, ast_inet_ntoa(trans->addr.sin_addr), sizeof(trans->parent->dei->ipaddr));
1828  }
1829  }
1830  if (ies.hint) {
1833  }
1834  }
1835  /* Close connection if not final */
1836  if (!final)
1837  dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
1838  }
1839 
1840  } else {
1841  /* Auth failure, check for data */
1842  if (!final) {
1843  /* Cancel if they didn't already */
1844  dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
1845  }
1846  }
1847  break;
1849  /* A dialplan response, lets see what we got... */
1850  if (ies.cause < 1) {
1851  int hasauth;
1852  /* Success of some sort */
1853  if (ast_test_flag(trans, FLAG_ENCRYPT)) {
1854  hasauth = encrypted;
1855  } else
1856  hasauth = 1;
1857 
1858  if (!hasauth) {
1859  ast_log(LOG_NOTICE, "Reponse to register not authorized!\n");
1860  if (!final) {
1861  dundi_ie_append_cause(ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Improper signature in answer");
1862  dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, ied);
1863  }
1864  } else {
1865  ast_debug(1, "Yay, we've registered as '%s' to '%s'\n", ast_eid_to_str(eid_str, sizeof(eid_str), &trans->us_eid),
1866  ast_eid_to_str(eid_str2, sizeof(eid_str2), &trans->them_eid));
1867  /* Close connection if not final */
1868  if (!final)
1869  dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
1870  }
1871  } else {
1872  /* Auth failure, cancel if they didn't for some reason */
1873  if (!final) {
1874  dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
1875  }
1876  }
1877  break;
1878  case DUNDI_COMMAND_INVALID:
1879  case DUNDI_COMMAND_NULL:
1881  /* Do nothing special */
1882  if (!final)
1883  dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
1884  break;
1885  case DUNDI_COMMAND_ENCREJ:
1886  if ((ast_test_flag(trans, FLAG_SENDFULLKEY)) || AST_LIST_EMPTY(&trans->lasttrans) || !(peer = find_peer(&trans->them_eid))) {
1887  /* No really, it's over at this point */
1888  if (!final)
1889  dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
1890  } else {
1891  /* Send with full key */
1893  if (final) {
1894  /* Ooops, we got a final message, start by sending ACK... */
1895  dundi_ack(trans, hdr->cmdresp & 0x80);
1896  trans->aseqno = trans->iseqno;
1897  /* Now, we gotta create a new transaction */
1898  if (!reset_transaction(trans)) {
1899  /* Make sure handle_frame doesn't destroy us */
1900  hdr->cmdresp &= 0x7f;
1901  /* Parse the message we transmitted */
1902  memset(&ies, 0, sizeof(ies));
1903  dundi_parse_ies(&ies, (AST_LIST_FIRST(&trans->lasttrans))->h->ies, (AST_LIST_FIRST(&trans->lasttrans))->datalen - sizeof(struct dundi_hdr));
1904  /* Reconstruct outgoing encrypted packet */
1905  memset(ied, 0, sizeof(*ied));
1906  dundi_ie_append_eid(ied, DUNDI_IE_EID, &trans->us_eid);
1908  dundi_ie_append_raw(ied, DUNDI_IE_SIGNATURE, peer->txenckey + 128, 128);
1909  if (ies.encblock)
1911  dundi_send(trans, DUNDI_COMMAND_ENCRYPT, 0, (AST_LIST_FIRST(&trans->lasttrans))->h->cmdresp & 0x80, ied);
1912  peer->sentfullkey = 1;
1913  }
1914  }
1915  }
1916  break;
1917  case DUNDI_COMMAND_ENCRYPT:
1918  if (!encrypted) {
1919  /* No nested encryption! */
1920  if ((trans->iseqno == 1) && !trans->oseqno) {
1921  if (!ies.eids[0] || !(peer = find_peer(ies.eids[0])) ||
1922  ((!ies.encsharedkey || !ies.encsig) && !ies.keycrc32) ||
1923  (check_key(peer, ies.encsharedkey, ies.encsig, ies.keycrc32) < 1)) {
1924  if (!final) {
1925  dundi_send(trans, DUNDI_COMMAND_ENCREJ, 0, 1, NULL);
1926  }
1927  break;
1928  }
1929  apply_peer(trans, peer);
1930  /* Key passed, use new contexts for this session */
1931  trans->ecx = peer->them_ecx;
1932  trans->dcx = peer->them_dcx;
1933  }
1934  if (ast_test_flag(trans, FLAG_ENCRYPT) && ies.encblock && ies.enclen) {
1935  struct dundi_hdr *dhdr;
1936  unsigned char decoded[MAX_PACKET_SIZE];
1937  int ddatalen;
1938  ddatalen = sizeof(decoded);
1939  dhdr = dundi_decrypt(trans, decoded, &ddatalen, hdr, ies.encblock, ies.enclen);
1940  if (dhdr) {
1941  /* Handle decrypted response */
1942  if (dundidebug)
1943  dundi_showframe(dhdr, 3, &trans->addr, ddatalen - sizeof(struct dundi_hdr));
1944  handle_command_response(trans, dhdr, ddatalen - sizeof(struct dundi_hdr), 1);
1945  /* Carry back final flag */
1946  hdr->cmdresp |= dhdr->cmdresp & 0x80;
1947  break;
1948  } else {
1949  ast_debug(1, "Ouch, decrypt failed :(\n");
1950  }
1951  }
1952  }
1953  if (!final) {
1954  /* Turn off encryption */
1955  ast_clear_flag(trans, FLAG_ENCRYPT);
1956  dundi_send(trans, DUNDI_COMMAND_ENCREJ, 0, 1, NULL);
1957  }
1958  break;
1959  default:
1960  /* Send unknown command if we don't know it, with final flag IFF it's the
1961  first command in the dialog and only if we haven't received final notification */
1962  if (!final) {
1964  dundi_send(trans, DUNDI_COMMAND_UNKNOWN, 0, !hdr->oseqno, ied);
1965  }
1966  }
1967 
1968  retval = 0;
1969 
1970 return_cleanup:
1971 #ifdef LOW_MEMORY
1972  ast_free(ied);
1973 #endif
1974  return retval;
1975 }
static void apply_peer(struct dundi_transaction *trans, struct dundi_peer *p)
Definition: pbx_dundi.c:1276
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:1069
struct sockaddr_in addr
Definition: pbx_dundi.c:296
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
unsigned char aseqno
Definition: pbx_dundi.c:256
static int reset_transaction(struct dundi_transaction *trans)
Definition: pbx_dundi.c:488
char country[80]
Definition: dundi.h:237
ast_aes_encrypt_key ecx
Definition: pbx_dundi.c:243
struct dundi_request * parent
Definition: pbx_dundi.c:259
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
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: utils.h:653
static int dundi_cache_time
Definition: pbx_dundi.c:187
#define DUNDI_COMMAND_ENCREJ
Definition: dundi.h:173
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Definition: netsock.c:222
static int do_register_expire(const void *data)
Definition: pbx_dundi.c:1301
#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:270
unsigned char encdata[0]
Definition: dundi.h:99
#define ast_clear_flag_nonstd(p, flag)
Definition: utils.h:180
int ast_sched_add(struct sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
Adds a scheduled event Schedule an event to take place at some point in the future. callback will be called with data as the argument, when milliseconds into the future (approximately) If callback returns 0, no further events will be re-scheduled.
Definition: sched.c:446
#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:371
char * q_org
Definition: dundi-parser.h:38
#define LOG_WARNING
Definition: logger.h:144
#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
static force_inline int inaddrcmp(const struct sockaddr_in *sin1, const struct sockaddr_in *sin2)
Compares the source address and port of two sockaddr_in.
Definition: network.h:90
char * dundi_eid_to_str_short(char *s, int maxlen, dundi_eid *eid)
Definition: dundi-parser.c:55
#define DUNDI_IE_CAUSE
Definition: dundi.h:191
Definition: sched.c:57
struct dundi_result * dr
Definition: pbx_dundi.c:269
int registerexpire
Definition: pbx_dundi.c:316
struct dundi_peer::@318 list
static void deep_copy_peer(struct dundi_peer *peer_dst, const struct dundi_peer *peer_src)
Definition: pbx_dundi.c:1523
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:3062
#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:4306
static int dundi_prop_precache(struct dundi_transaction *trans, struct dundi_ies *ies, char *ccontext)
Definition: pbx_dundi.c:922
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:1384
struct packetlist lasttrans
Definition: pbx_dundi.c:258
dundi_eid us_eid
Definition: pbx_dundi.c:241
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:265
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:242
#define ast_verb(level,...)
Definition: logger.h:243
ast_aes_decrypt_key them_dcx
Definition: pbx_dundi.c:314
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
Definition: netsock.c:320
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:358
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:236
#define DUNDI_COMMAND_DPRESPONSE
Definition: dundi.h:161
#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:846
unsigned char protocol
Definition: dundi.h:104
static struct dundi_peer * any_peer
Wildcard peer.
Definition: pbx_dundi.c:343
#define AST_SCHED_DEL(sched, id)
a loop construct to ensure that the scheduled task get deleted. The idea is that if we loop attemptin...
Definition: sched.h:51
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:183
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define DUNDI_MODEL_INBOUND
Definition: pbx_dundi.c:151
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:267
#define DUNDI_IE_EID
Definition: dundi.h:182
char eid_str[20]
Definition: dundi.h:231
dundi_eid us_eid
Definition: pbx_dundi.c:299
static int default_expiration
Definition: pbx_dundi.c:190
int expiration
Definition: dundi.h:228
void dundi_showframe(struct dundi_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen)
Definition: dundi-parser.c:433
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:313
char * q_stateprov
Definition: dundi-parser.h:40
unsigned int dynamic
Definition: pbx_dundi.c:325
static int dundi_answer_entity(struct dundi_transaction *trans, struct dundi_ies *ies, char *ccontext)
Definition: pbx_dundi.c:791
#define DUNDI_COMMAND_UNKNOWN
Definition: dundi.h:167
char number[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:266
static struct dundi_peer * find_peer(dundi_eid *eid)
Definition: pbx_dundi.c:504
int dundi_ie_append_cause(struct dundi_ie_data *ied, unsigned char ie, unsigned char cause, char *data)
Definition: dundi-parser.c:499
unsigned char * encsig
Definition: dundi-parser.h:47
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int techint
Definition: dundi.h:229
unsigned char oseqno
Definition: pbx_dundi.c:255
int anscount
Definition: dundi-parser.h:30
#define LOG_NOTICE
Definition: logger.h:133
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:1470
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:696
unsigned short weight
Definition: dundi.h:106
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: utils.c:564
char * called_context
Definition: dundi-parser.h:26
#define ast_free(a)
Definition: astmm.h:97
struct dundi_hint_metadata * hmd
Definition: pbx_dundi.c:271
unsigned int flags
Definition: dundi.h:226
dundi_eid eid
Definition: pbx_dundi.c:295
struct sockaddr_in addr
Definition: pbx_dundi.c:237
char inkey[80]
Definition: pbx_dundi.c:300
char exten[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:224
struct dundi_peer::permissionlist permit
#define ast_clear_flag(p, flag)
Definition: utils.h:77
#define DUNDI_COMMAND_PRECACHERQ
Definition: dundi.h:164
int pcmodel
Definition: pbx_dundi.c:323
#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:298
#define DUNDI_COMMAND_REGREQ
Definition: dundi.h:169
unsigned char txenckey[256]
Definition: pbx_dundi.c:307
#define DUNDI_COMMAND_EIDRESPONSE
Definition: dundi.h:163
#define ast_calloc(a, b)
Definition: astmm.h:82
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static int handle_command_response(struct dundi_transaction *trans, struct dundi_hdr *hdr, int datalen, int encrypted)
Definition: pbx_dundi.c:1553
#define DUNDI_COMMAND_EIDQUERY
Definition: dundi.h:162
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:881
#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: db.c:260
#define DUNDI_COMMAND_DPDISCOVER
Definition: dundi.h:160
static int dundi_ack(struct dundi_transaction *trans, int final)
Definition: pbx_dundi.c:440
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:253
#define ast_set_flag_nonstd(p, flag)
Definition: utils.h:176
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:147
#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:244
#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:305
#define DUNDI_COMMAND_REGRESPONSE
Definition: dundi.h:170
unsigned char data[0]
Definition: dundi.h:107
#define DUNDI_COMMAND_CANCEL
Definition: dundi.h:171
static int handle_frame ( struct dundi_hdr h,
struct sockaddr_in *  sin,
int  datalen 
)
static

Definition at line 2010 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().

2011 {
2012  struct dundi_transaction *trans;
2013  trans = find_transaction(h, sin);
2014  if (!trans) {
2015  dundi_reject(h, sin);
2016  return 0;
2017  }
2018  /* Got a transaction, see where this header fits in */
2019  if (h->oseqno == trans->iseqno) {
2020  /* Just what we were looking for... Anything but ack increments iseqno */
2021  if (ack_trans(trans, h->iseqno) && ast_test_flag(trans, FLAG_FINAL)) {
2022  /* If final, we're done */
2023  destroy_trans(trans, 0);
2024  return 0;
2025  }
2026  if (h->cmdresp != DUNDI_COMMAND_ACK) {
2027  trans->oiseqno = trans->iseqno;
2028  trans->iseqno++;
2029  handle_command_response(trans, h, datalen, 0);
2030  }
2031  if (trans->aseqno != trans->iseqno) {
2032  dundi_ack(trans, h->cmdresp & 0x80);
2033  trans->aseqno = trans->iseqno;
2034  }
2035  /* Delete any saved last transmissions */
2036  destroy_packets(&trans->lasttrans);
2037  if (h->cmdresp & 0x80) {
2038  /* Final -- destroy now */
2039  destroy_trans(trans, 0);
2040  }
2041  } else if (h->oseqno == trans->oiseqno) {
2042  /* Last incoming sequence number -- send ACK without processing */
2043  dundi_ack(trans, 0);
2044  } else {
2045  /* Out of window -- simply drop */
2046  ast_debug(1, "Dropping packet out of window!\n");
2047  }
2048  return 0;
2049 }
unsigned char aseqno
Definition: pbx_dundi.c:256
#define ast_test_flag(p, flag)
Definition: utils.h:63
unsigned char cmdresp
Definition: dundi.h:39
struct packetlist lasttrans
Definition: pbx_dundi.c:258
unsigned char oseqno
Definition: dundi.h:38
static void destroy_trans(struct dundi_transaction *trans, int fromtimeout)
Definition: pbx_dundi.c:2956
#define DUNDI_COMMAND_ACK
Definition: dundi.h:159
static struct dundi_transaction * find_transaction(struct dundi_hdr *hdr, struct sockaddr_in *sin)
Definition: pbx_dundi.c:402
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static void dundi_reject(struct dundi_hdr *h, struct sockaddr_in *sin)
Definition: pbx_dundi.c:444
unsigned char oiseqno
Definition: pbx_dundi.c:254
static void destroy_packets(struct packetlist *p)
Definition: pbx_dundi.c:1978
static int handle_command_response(struct dundi_transaction *trans, struct dundi_hdr *hdr, int datalen, int encrypted)
Definition: pbx_dundi.c:1553
static int ack_trans(struct dundi_transaction *trans, int iseqno)
Definition: pbx_dundi.c:1989
static int dundi_ack(struct dundi_transaction *trans, int final)
Definition: pbx_dundi.c:440
unsigned char iseqno
Definition: pbx_dundi.c:253
unsigned char iseqno
Definition: dundi.h:37
static int has_permission ( struct permissionlist *  permlist,
char *  cont 
)
static

Definition at line 358 of file pbx_dundi.c.

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

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

359 {
360  struct permission *perm;
361  int res = 0;
362 
363  AST_LIST_TRAVERSE(permlist, perm, list) {
364  if (!strcasecmp(perm->name, "all") || !strcasecmp(perm->name, cont))
365  res = perm->allow;
366  }
367 
368  return res;
369 }
#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:209
struct permission::@310 list
static int load_module ( void  )
static

Definition at line 4809 of file pbx_dundi.c.

References ARRAY_LEN, ast_cli_register_multiple(), ast_custom_function_register, ast_inet_ntoa(), ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_netsock_set_qos(), ast_register_switch(), ast_verb, dundi_debug_output(), dundi_error_output(), DUNDI_PORT, dundi_set_error(), dundi_set_output(), errno, io_context_create(), LOG_ERROR, sched_context_create(), set_config(), and start_network_thread().

4810 {
4811  struct sockaddr_in sin;
4812 
4815 
4816  sin.sin_family = AF_INET;
4817  sin.sin_port = htons(DUNDI_PORT);
4818  sin.sin_addr.s_addr = INADDR_ANY;
4819 
4820  /* Make a UDP socket */
4821  io = io_context_create();
4823 
4824  if (!io || !sched)
4825  return AST_MODULE_LOAD_DECLINE;
4826 
4827  if (set_config("dundi.conf", &sin, 0))
4828  return AST_MODULE_LOAD_DECLINE;
4829 
4830  netsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
4831 
4832  if (netsocket < 0) {
4833  ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno));
4834  return AST_MODULE_LOAD_DECLINE;
4835  }
4836  if (bind(netsocket, (struct sockaddr *) &sin, sizeof(sin))) {
4837  ast_log(LOG_ERROR, "Unable to bind to %s port %d: %s\n",
4838  ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), strerror(errno));
4839  return AST_MODULE_LOAD_DECLINE;
4840  }
4841 
4842  ast_netsock_set_qos(netsocket, tos, 0, "DUNDi");
4843 
4844  if (start_network_thread()) {
4845  ast_log(LOG_ERROR, "Unable to start network thread\n");
4846  close(netsocket);
4847  return AST_MODULE_LOAD_DECLINE;
4848  }
4849 
4852  ast_log(LOG_ERROR, "Unable to register DUNDi switch\n");
4856 
4857  ast_verb(2, "DUNDi Ready and Listening on %s port %d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
4858 
4859  return AST_MODULE_LOAD_SUCCESS;
4860 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static unsigned int tos
Definition: chan_h323.c:146
#define DUNDI_PORT
Definition: dundi.h:30
void dundi_set_error(void(*func)(const char *))
Definition: dundi-parser.c:630
static int start_network_thread(void)
Definition: pbx_dundi.c:2261
static struct io_context * io
Definition: pbx_dundi.c:176
Definition: sched.c:57
int ast_netsock_set_qos(int netsocket, int tos, int cos, const char *desc)
Definition: netsock.c:158
#define ast_verb(level,...)
Definition: logger.h:243
static int netsocket
Definition: pbx_dundi.c:178
void dundi_set_output(void(*func)(const char *))
Definition: dundi-parser.c:625
static int set_config(char *config_file, struct sockaddr_in *sin, int reload)
Definition: pbx_dundi.c:4621
static void dundi_debug_output(const char *data)
Definition: pbx_dundi.c:347
static struct ast_custom_function dundi_function
Definition: pbx_dundi.c:3939
#define LOG_ERROR
Definition: logger.h:155
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int errno
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: utils.c:564
int ast_register_switch(struct ast_switch *sw)
Register an alternative dialplan switch.
Definition: pbx.c:6439
static struct ast_cli_entry cli_dundi[]
Definition: pbx_dundi.c:2884
static void dundi_error_output(const char *data)
Definition: pbx_dundi.c:353
struct sched_context * sched_context_create(void)
New schedule context.
Definition: sched.c:246
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
Definition: cli.c:2167
static struct ast_custom_function dundi_query_function
Definition: pbx_dundi.c:4027
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1164
static struct ast_switch dundi_switch
Definition: pbx_dundi.c:4612
static struct ast_custom_function dundi_result_function
Definition: pbx_dundi.c:4101
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:76
static void load_password ( void  )
static

Definition at line 2107 of file pbx_dundi.c.

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

Referenced by set_config().

2108 {
2109  char *current=NULL;
2110  char *last=NULL;
2111  char tmp[256];
2112  time_t expired;
2113 
2114  ast_db_get(secretpath, "secretexpiry", tmp, sizeof(tmp));
2115  if (!ast_get_time_t(tmp, &expired, 0, NULL)) {
2116  ast_db_get(secretpath, "secret", tmp, sizeof(tmp));
2117  current = strchr(tmp, ';');
2118  if (!current)
2119  current = tmp;
2120  else {
2121  *current = '\0';
2122  current++;
2123  };
2124  if ((time(NULL) - expired) < 0) {
2125  if ((expired - time(NULL)) > DUNDI_SECRET_TIME)
2126  expired = time(NULL) + DUNDI_SECRET_TIME;
2127  } else if ((time(NULL) - (expired + DUNDI_SECRET_TIME)) < 0) {
2128  last = current;
2129  current = NULL;
2130  } else {
2131  last = NULL;
2132  current = NULL;
2133  }
2134  }
2135  if (current) {
2136  /* Current key is still valid, just setup rotatation properly */
2137  ast_copy_string(cursecret, current, sizeof(cursecret));
2138  rotatetime = expired;
2139  } else {
2140  /* Current key is out of date, rotate or eliminate all together */
2141  build_secret(cursecret, sizeof(cursecret));
2142  save_secret(cursecret, last);
2143  }
2144 }
int ast_db_get(const char *family, const char *key, char *out, int outlen)
Get key value specified by family/key.
Definition: db.c:348
static char secretpath[80]
Definition: pbx_dundi.c:199
int ast_get_time_t(const char *src, time_t *dst, time_t _default, int *consumed)
get values from config variables.
Definition: utils.c:2118
static void save_secret(const char *newkey, const char *oldkey)
Definition: pbx_dundi.c:2094
struct sla_ringing_trunk * last
Definition: app_meetme.c:965
#define DUNDI_SECRET_TIME
Definition: pbx_dundi.c:173
static void build_secret(char *secret, int seclen)
Definition: pbx_dundi.c:2079
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static time_t rotatetime
Definition: pbx_dundi.c:202
static char cursecret[80]
Definition: pbx_dundi.c:200
static void mark_mappings ( void  )
static

Definition at line 4116 of file pbx_dundi.c.

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

Referenced by set_config(), and unload_module().

4117 {
4118  struct dundi_mapping *map;
4119 
4120  AST_LIST_LOCK(&peers);
4121  AST_LIST_TRAVERSE(&mappings, map, list) {
4122  map->dead = 1;
4123  }
4125 }
struct dundi_mapping::@317 list
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
static int * map
Definition: misdn_config.c:434
#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
static void mark_peers ( void  )
static

Definition at line 4106 of file pbx_dundi.c.

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

Referenced by set_config(), and unload_module().

4107 {
4108  struct dundi_peer *peer;
4109  AST_LIST_LOCK(&peers);
4110  AST_LIST_TRAVERSE(&peers, peer, list) {
4111  peer->dead = 1;
4112  }
4114 }
#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_peer::@318 list
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
static char* model2str ( int  model)
static

Definition at line 2367 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().

2368 {
2369  switch(model) {
2370  case DUNDI_MODEL_INBOUND:
2371  return "Inbound";
2372  case DUNDI_MODEL_OUTBOUND:
2373  return "Outbound";
2374  case DUNDI_MODEL_SYMMETRIC:
2375  return "Symmetric";
2376  default:
2377  return "Unknown";
2378  }
2379 }
#define DUNDI_MODEL_SYMMETRIC
Definition: pbx_dundi.c:153
#define DUNDI_MODEL_INBOUND
Definition: pbx_dundi.c:151
#define DUNDI_MODEL_OUTBOUND
Definition: pbx_dundi.c:152
static void* network_thread ( void *  ignore)
static

Definition at line 2163 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_PTHREADT_NULL, ast_sched_runq(), ast_sched_wait(), check_password(), and socket_read().

Referenced by start_network_thread().

2164 {
2165  /* Our job is simple: Send queued messages, retrying if necessary. Read frames
2166  from the network, and queue them for delivery to the channels */
2167  int res;
2168  /* Establish I/O callback for socket read */
2169  int *socket_read_id = ast_io_add(io, netsocket, socket_read, AST_IO_IN, NULL);
2170 
2171  while (!dundi_shutdown) {
2172  res = ast_sched_wait(sched);
2173  if ((res > 1000) || (res < 0))
2174  res = 1000;
2175  res = ast_io_wait(io, res);
2176  if (res >= 0) {
2177  AST_LIST_LOCK(&peers);
2180  }
2181  check_password();
2182  }
2183 
2184  ast_io_remove(io, socket_read_id);
2186 
2187  return NULL;
2188 }
int ast_io_wait(struct io_context *ioc, int howlong)
Waits for IO.
Definition: io.c:273
#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
static struct io_context * io
Definition: pbx_dundi.c:176
#define AST_IO_IN
Definition: io.h:33
Definition: sched.c:57
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:157
static pthread_t netthreadid
Definition: pbx_dundi.c:179
static int netsocket
Definition: pbx_dundi.c:178
#define AST_PTHREADT_NULL
Definition: lock.h:65
static int socket_read(int *id, int fd, short events, void *cbdata)
Definition: pbx_dundi.c:2051
static void check_password(void)
Definition: pbx_dundi.c:2146
static int dundi_shutdown
Definition: pbx_dundi.c:204
int ast_io_remove(struct io_context *ioc, int *id)
Removes an IO context.
Definition: io.c:240
int ast_sched_runq(struct sched_context *con)
Runs the queue.
Definition: sched.c:600
int ast_sched_wait(struct sched_context *con) attribute_warn_unused_result
Determines number of seconds until the next outstanding event to take place Determine the number of s...
Definition: sched.c:334
static int optimize_transactions ( struct dundi_request dr,
int  order 
)
static

Definition at line 3337 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, dundi_peer::order, dundi_transaction::them_eid, dundi_request::trans, and dundi_transaction::us_eid.

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

3338 {
3339  /* Minimize the message propagation through DUNDi by
3340  alerting the network to hops which should be not be considered */
3341  struct dundi_transaction *trans;
3342  struct dundi_peer *peer;
3343  dundi_eid tmp;
3344  int x;
3345  int needpush;
3346 
3347  AST_LIST_LOCK(&peers);
3348  AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) {
3349  /* Pop off the true root */
3350  if (trans->eidcount) {
3351  tmp = trans->eids[--trans->eidcount];
3352  needpush = 1;
3353  } else {
3354  tmp = trans->us_eid;
3355  needpush = 0;
3356  }
3357 
3358  AST_LIST_TRAVERSE(&peers, peer, list) {
3359  if (ast_eid_cmp(&peer->eid, &empty_eid) && /* peer's eid is not empty (in case of dynamic peers) */
3360  (peer->lastms > -1) && /* peer is reachable */
3361  has_permission(&peer->include, dr->dcontext) && /* peer has destination context */
3362  ast_eid_cmp(&peer->eid, &trans->them_eid) && /* peer is not transaction endpoint */
3363  (peer->order <= order)) {
3364  /* For each other transaction, make sure we don't
3365  ask this EID about the others if they're not
3366  already in the list */
3367  if (!ast_eid_cmp(&tmp, &peer->eid))
3368  x = -1;
3369  else {
3370  for (x=0;x<trans->eidcount;x++) {
3371  if (!ast_eid_cmp(&trans->eids[x], &peer->eid))
3372  break;
3373  }
3374  }
3375  if (x == trans->eidcount) {
3376  /* Nope not in the list, if needed, add us at the end since we're the source */
3377  if (trans->eidcount < DUNDI_MAX_STACK - needpush) {
3378  trans->eids[trans->eidcount++] = peer->eid;
3379  /* Need to insert the real root (or us) at the bottom now as
3380  a requirement now. */
3381  needpush = 1;
3382  }
3383  }
3384  }
3385  }
3386  /* If necessary, push the true root back on the end */
3387  if (needpush)
3388  trans->eids[trans->eidcount++] = tmp;
3389  }
3391 
3392  return 0;
3393 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
dundi_eid eids[DUNDI_MAX_STACK+1]
Definition: pbx_dundi.c:239
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
struct dundi_peer::@318 list
dundi_eid us_eid
Definition: pbx_dundi.c:241
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:265
dundi_eid them_eid
Definition: pbx_dundi.c:242
An Entity ID is essentially a MAC address, brief and unique.
Definition: utils.h:808
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
Definition: netsock.c:320
int lastms
Definition: pbx_dundi.c:326
static int has_permission(struct permissionlist *permlist, char *cont)
Definition: pbx_dundi.c:358
static dundi_eid empty_eid
Definition: pbx_dundi.c:203
#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:295
#define DUNDI_MAX_STACK
Definition: dundi-parser.h:18
struct permissionlist include
Definition: pbx_dundi.c:298
struct dundi_request::@315 trans
static void populate_addr ( struct dundi_peer peer,
dundi_eid eid 
)
static

Definition at line 4329 of file pbx_dundi.c.

References dundi_peer::addr, ast_db_get(), ast_eid_to_str(), ast_sched_add(), do_register_expire(), inet_aton(), and dundi_peer::registerexpire.

Referenced by build_peer().

4330 {
4331  char data[256];
4332  char *c;
4333  int port, expire;
4334  char eid_str[20];
4335  ast_eid_to_str(eid_str, sizeof(eid_str), eid);
4336  if (!ast_db_get("dundi/dpeers", eid_str, data, sizeof(data))) {
4337  c = strchr(data, ':');
4338  if (c) {
4339  *c = '\0';
4340  c++;
4341  if (sscanf(c, "%5d:%30d", &port, &expire) == 2) {
4342  /* Got it! */
4343  inet_aton(data, &peer->addr.sin_addr);
4344  peer->addr.sin_family = AF_INET;
4345  peer->addr.sin_port = htons(port);
4346  peer->registerexpire = ast_sched_add(sched, (expire + 10) * 1000, do_register_expire, peer);
4347  }
4348  }
4349  }
4350 }
struct sockaddr_in addr
Definition: pbx_dundi.c:296
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Definition: netsock.c:222
static int do_register_expire(const void *data)
Definition: pbx_dundi.c:1301
int ast_db_get(const char *family, const char *key, char *out, int outlen)
Get key value specified by family/key.
Definition: db.c:348
int ast_sched_add(struct sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
Adds a scheduled event Schedule an event to take place at some point in the future. callback will be called with data as the argument, when milliseconds into the future (approximately) If callback returns 0, no further events will be re-scheduled.
Definition: sched.c:446
Definition: sched.c:57
int registerexpire
Definition: pbx_dundi.c:316
int inet_aton(const char *cp, struct in_addr *pin)
static int precache_trans ( struct dundi_transaction trans,
struct dundi_mapping maps,
int  mapcount,
int *  minexp,
int *  foundanswers 
)
static

Definition at line 3190 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, dundi_request::number, dundi_transaction::parent, dundi_transaction::them_eid, dundi_transaction::ttl, dundi_transaction::us_eid, and dundi_result::weight.

Referenced by precache_transactions().

3191 {
3192  struct dundi_ie_data ied;
3193  int x, res;
3194  int max = 999999;
3195  int expiration = dundi_cache_time;
3196  int ouranswers=0;
3197  dundi_eid *avoid[1] = { NULL, };
3198  int direct[1] = { 0, };
3199  struct dundi_result dr[MAX_RESULTS];
3200  struct dundi_hint_metadata hmd;
3201  if (!trans->parent) {
3202  ast_log(LOG_WARNING, "Tried to discover a transaction with no parent?!?\n");
3203  return -1;
3204  }
3205  memset(&hmd, 0, sizeof(hmd));
3206  memset(&dr, 0, sizeof(dr));
3207  /* Look up the answers we're going to include */
3208  for (x=0;x<mapcount;x++)
3209  ouranswers = dundi_lookup_local(dr, maps + x, trans->parent->number, &trans->us_eid, ouranswers, &hmd);
3210  if (ouranswers < 0)
3211  ouranswers = 0;
3212  for (x=0;x<ouranswers;x++) {
3213  if (dr[x].weight < max)
3214  max = dr[x].weight;
3215  }
3216  if (max) {
3217  /* If we do not have a canonical result, keep looking */
3218  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);
3219  if (res > 0) {
3220  /* Append answer in result */
3221  ouranswers += res;
3222  }
3223  }
3224 
3225  if (ouranswers > 0) {
3226  *foundanswers += ouranswers;
3227  memset(&ied, 0, sizeof(ied));
3229  if (!dundi_eid_zero(&trans->us_eid))
3230  dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid);
3231  for (x=0;x<trans->eidcount;x++)
3232  dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->eids[x]);
3235  dundi_ie_append_short(&ied, DUNDI_IE_TTL, trans->ttl);
3236  for (x=0;x<ouranswers;x++) {
3237  /* Add answers */
3238  if (dr[x].expiration && (expiration > dr[x].expiration))
3239  expiration = dr[x].expiration;
3240  dundi_ie_append_answer(&ied, DUNDI_IE_ANSWER, &dr[x].eid, dr[x].techint, dr[x].flags, dr[x].weight, dr[x].dest);
3241  }
3242  dundi_ie_append_hint(&ied, DUNDI_IE_HINT, hmd.flags, hmd.exten);
3243  dundi_ie_append_short(&ied, DUNDI_IE_EXPIRATION, expiration);
3244  if (trans->autokilltimeout)
3245  trans->autokillid = ast_sched_add(sched, trans->autokilltimeout, do_autokill, trans);
3246  if (expiration < *minexp)
3247  *minexp = expiration;
3248  return dundi_send(trans, DUNDI_COMMAND_PRECACHERQ, 0, 0, &ied);
3249  } else {
3250  /* Oops, nothing to send... */
3251  destroy_trans(trans, 0);
3252  return 0;
3253  }
3254 }
static float dr[4]
Definition: tdd.c:59
#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:562
struct dundi_request * parent
Definition: pbx_dundi.c:259
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:187
int ast_sched_add(struct sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
Adds a scheduled event Schedule an event to take place at some point in the future. callback will be called with data as the argument, when milliseconds into the future (approximately) If callback returns 0, no further events will be re-scheduled.
Definition: sched.c:446
dundi_eid eids[DUNDI_MAX_STACK+1]
Definition: pbx_dundi.c:239
#define LOG_WARNING
Definition: logger.h:144
#define MAX_RESULTS
Definition: pbx_dundi.c:145
Definition: sched.c:57
static int dundi_send(struct dundi_transaction *trans, int cmdresp, int flags, int final, struct dundi_ie_data *ied)
Definition: pbx_dundi.c:3062
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:3576
dundi_eid us_eid
Definition: pbx_dundi.c:241
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:265
#define DUNDI_IE_VERSION
Definition: dundi.h:188
static void destroy_trans(struct dundi_transaction *trans, int fromtimeout)
Definition: pbx_dundi.c:2956
dundi_eid them_eid
Definition: pbx_dundi.c:242
An Entity ID is essentially a MAC address, brief and unique.
Definition: utils.h:808
#define DUNDI_IE_EID
Definition: dundi.h:182
static int do_autokill(const void *data)
Definition: pbx_dundi.c:3133
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:266
#define DUNDI_IE_CALLED_CONTEXT
Definition: dundi.h:183
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#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:223
#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:83
#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
static int precache_transactions ( struct dundi_request dr,
struct dundi_mapping maps,
int  mapcount,
int *  expiration,
int *  foundanswers 
)
static

Definition at line 3289 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, precache_trans(), dundi_transaction::thread, and dundi_request::trans.

Referenced by dundi_precache_internal().

3290 {
3291  struct dundi_transaction *trans;
3292 
3293  /* Mark all as "in thread" so they don't disappear */
3294  AST_LIST_LOCK(&peers);
3295  AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) {
3296  if (trans->thread)
3297  ast_log(LOG_WARNING, "This shouldn't happen, really...\n");
3298  trans->thread = 1;
3299  }
3301 
3302  AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) {
3303  if (!ast_test_flag(trans, FLAG_DEAD))
3304  precache_trans(trans, maps, mapcount, expiration, foundanswers);
3305  }
3306 
3307  /* Cleanup any that got destroyed in the mean time */
3308  AST_LIST_LOCK(&peers);
3310  trans->thread = 0;
3311  if (ast_test_flag(trans, FLAG_DEAD)) {
3312  ast_debug(1, "Our transaction went away!\n");
3313  /* This is going to remove the transaction from the dundi_request's list, as well
3314  * as the global transactions list */
3315  destroy_trans(trans, 0);
3316  }
3317  }
3320 
3321  return 0;
3322 }
#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:144
#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:2956
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:600
static int precache_trans(struct dundi_transaction *trans, struct dundi_mapping *maps, int mapcount, int *minexp, int *foundanswers)
Definition: pbx_dundi.c:3190
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct dundi_request::@315 trans
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
struct dundi_transaction::@313 parentlist
static void* process_clearcache ( void *  ignore)
static

Definition at line 2190 of file pbx_dundi.c.

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

Referenced by start_network_thread().

2191 {
2192  struct ast_db_entry *db_entry, *db_tree;
2193  int striplen = sizeof("/dundi/cache");
2194  time_t now;
2195 
2196  while (!dundi_shutdown) {
2197  pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
2198 
2199  time(&now);
2200 
2201  db_entry = db_tree = ast_db_gettree("dundi/cache", NULL);
2202  for (; db_entry; db_entry = db_entry->next) {
2203  time_t expiry;
2204 
2205  if (!ast_get_time_t(db_entry->data, &expiry, 0, NULL)) {
2206  if (expiry < now) {
2207  ast_debug(1, "clearing expired DUNDI cache entry: %s\n", db_entry->key);
2208  ast_db_del("dundi/cache", db_entry->key + striplen);
2209  }
2210  }
2211  }
2212  ast_db_freetree(db_tree);
2213 
2214  pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
2215  pthread_testcancel();
2216  sleep(60);
2217  pthread_testcancel();
2218  }
2219 
2221  return NULL;
2222 }
void ast_db_freetree(struct ast_db_entry *entry)
Free structure created by ast_db_gettree()
Definition: db.c:656
int ast_get_time_t(const char *src, time_t *dst, time_t _default, int *consumed)
get values from config variables.
Definition: utils.c:2118
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
struct ast_db_entry * next
Definition: astdb.h:31
#define AST_PTHREADT_NULL
Definition: lock.h:65
struct ast_db_entry * ast_db_gettree(const char *family, const char *keytree)
Get a list of values within the astdb tree If family is specified, only those keys will be returned...
Definition: db.c:631
static pthread_t clearcachethreadid
Definition: pbx_dundi.c:181
Definition: astdb.h:30
char data[0]
Definition: astdb.h:33
static int dundi_shutdown
Definition: pbx_dundi.c:204
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: db.c:365
char * key
Definition: astdb.h:32
static void* process_precache ( void *  ign)
static

Definition at line 2224 of file pbx_dundi.c.

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

Referenced by start_network_thread().

2225 {
2226  struct dundi_precache_queue *qe;
2227  time_t now;
2228  char context[256];
2229  char number[256];
2230  int run;
2231 
2232  while (!dundi_shutdown) {
2233  time(&now);
2234  run = 0;
2235  AST_LIST_LOCK(&pcq);
2236  if ((qe = AST_LIST_FIRST(&pcq))) {
2237  if (!qe->expiration) {
2238  /* Gone... Remove... */
2240  ast_free(qe);
2241  } else if (qe->expiration < now) {
2242  /* Process this entry */
2243  qe->expiration = 0;
2244  ast_copy_string(context, qe->context, sizeof(context));
2245  ast_copy_string(number, qe->number, sizeof(number));
2246  run = 1;
2247  }
2248  }
2249  AST_LIST_UNLOCK(&pcq);
2250  if (run) {
2251  dundi_precache(context, number);
2252  } else
2253  sleep(1);
2254  }
2255 
2257 
2258  return NULL;
2259 }
Definition: pbx_dundi.c:333
#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
int dundi_precache(const char *dcontext, const char *number)
Pre-cache to push upstream peers.
Definition: pbx_dundi.c:3821
static pthread_t precachethreadid
Definition: pbx_dundi.c:180
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
Number structure.
Definition: app_followme.c:109
#define AST_PTHREADT_NULL
Definition: lock.h:65
struct dundi_precache_queue::@312 list
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
#define ast_free(a)
Definition: astmm.h:97
static int dundi_shutdown
Definition: pbx_dundi.c:204
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static void prune_mappings ( void  )
static

Definition at line 4168 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(), and map.

Referenced by set_config(), and unload_module().

4169 {
4170  struct dundi_mapping *map;
4171 
4172  AST_LIST_LOCK(&peers);
4174  if (map->dead) {
4176  destroy_map(map);
4177  }
4178  }
4181 }
struct dundi_mapping::@317 list
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
static void destroy_map(struct dundi_mapping *map)
Definition: pbx_dundi.c:4146
static int * map
Definition: misdn_config.c:434
#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:600
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:554
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
static void prune_peers ( void  )
static

Definition at line 4153 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, and destroy_peer().

Referenced by set_config(), and unload_module().

4154 {
4155  struct dundi_peer *peer;
4156 
4157  AST_LIST_LOCK(&peers);
4159  if (peer->dead) {
4161  destroy_peer(peer);
4162  }
4163  }
4166 }
#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_peer::@318 list
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:600
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:554
static void destroy_peer(struct dundi_peer *peer)
Definition: pbx_dundi.c:4135
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
static void qualify_peer ( struct dundi_peer peer,
int  schedonly 
)
static

Definition at line 4306 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, dundi_peer::qualifyid, dundi_peer::qualtrans, and dundi_peer::qualtx.

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

4307 {
4308  int when;
4309  AST_SCHED_DEL(sched, peer->qualifyid);
4310  if (peer->qualtrans)
4311  destroy_trans(peer->qualtrans, 0);
4312  peer->qualtrans = NULL;
4313  if (peer->maxms > 0) {
4314  when = 60000;
4315  if (peer->lastms < 0)
4316  when = 10000;
4317  if (schedonly)
4318  when = 5000;
4319  peer->qualifyid = ast_sched_add(sched, when, do_qualify, peer);
4320  if (!schedonly)
4321  peer->qualtrans = create_transaction(peer);
4322  if (peer->qualtrans) {
4323  peer->qualtx = ast_tvnow();
4325  dundi_send(peer->qualtrans, DUNDI_COMMAND_NULL, 0, 1, NULL);
4326  }
4327  }
4328 }
int qualifyid
Definition: pbx_dundi.c:304
int ast_sched_add(struct sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
Adds a scheduled event Schedule an event to take place at some point in the future. callback will be called with data as the argument, when milliseconds into the future (approximately) If callback returns 0, no further events will be re-scheduled.
Definition: sched.c:446
#define ast_set_flag(p, flag)
Definition: utils.h:70
Definition: sched.c:57
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
static int dundi_send(struct dundi_transaction *trans, int cmdresp, int flags, int final, struct dundi_ie_data *ied)
Definition: pbx_dundi.c:3062
static void destroy_trans(struct dundi_transaction *trans, int fromtimeout)
Definition: pbx_dundi.c:2956
int lastms
Definition: pbx_dundi.c:326
struct timeval qualtx
Definition: pbx_dundi.c:328
static struct dundi_transaction * create_transaction(struct dundi_peer *p)
Definition: pbx_dundi.c:2900
#define AST_SCHED_DEL(sched, id)
a loop construct to ensure that the scheduled task get deleted. The idea is that if we loop attemptin...
Definition: sched.h:51
struct dundi_transaction * qualtrans
Definition: pbx_dundi.c:321
static int do_qualify(const void *data)
Definition: pbx_dundi.c:4298
#define DUNDI_COMMAND_NULL
Definition: dundi.h:168
static int query_transactions ( struct dundi_request dr)
static

Definition at line 3324 of file pbx_dundi.c.

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

Referenced by dundi_query_eid_internal().

3325 {
3326  struct dundi_transaction *trans;
3327 
3328  AST_LIST_LOCK(&peers);
3329  AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) {
3330  dundi_query(trans);
3331  }
3333 
3334  return 0;
3335 }
#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
static int dundi_query(struct dundi_transaction *trans)
Definition: pbx_dundi.c:3256
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct dundi_request::@315 trans
struct dundi_transaction::@313 parentlist
static int register_request ( struct dundi_request dr,
struct dundi_request **  pending 
)
static

Definition at line 3510 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, dundi_request::number, and dundi_request::root_eid.

Referenced by dundi_lookup_internal().

3511 {
3512  struct dundi_request *cur;
3513  int res=0;
3514  char eid_str[20];
3515  AST_LIST_LOCK(&peers);
3516  AST_LIST_TRAVERSE(&requests, cur, list) {
3517  ast_debug(1, "Checking '%s@%s' vs '%s@%s'\n", cur->dcontext, cur->number,
3518  dr->dcontext, dr->number);
3519  if (!strcasecmp(cur->dcontext, dr->dcontext) &&
3520  !strcasecmp(cur->number, dr->number) &&
3521  (!ast_eid_cmp(&cur->root_eid, &dr->root_eid) || (cur->crc32 == dr->crc32))) {
3522  ast_debug(1, "Found existing query for '%s@%s' for '%s' crc '%08x'\n",
3523  cur->dcontext, cur->number, ast_eid_to_str(eid_str, sizeof(eid_str), &cur->root_eid), cur->crc32);
3524  *pending = cur;
3525  res = 1;
3526  break;
3527  }
3528  }
3529  if (!res) {
3530  ast_debug(1, "Registering request for '%s@%s' on behalf of '%s' crc '%08x'\n",
3531  dr->number, dr->dcontext, ast_eid_to_str(eid_str, sizeof(eid_str), &dr->root_eid), dr->crc32);
3532  /* Go ahead and link us in since nobody else is searching for this */
3534  *pending = NULL;
3535  }
3537  return res;
3538 }
#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)
Definition: netsock.c:222
struct dundi_request::@316 list
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
char dcontext[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:265
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
Definition: netsock.c:320
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
char number[AST_MAX_EXTENSION]
Definition: pbx_dundi.c:266
uint32_t crc32
Definition: pbx_dundi.c:277
#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:696
dundi_eid root_eid
Definition: pbx_dundi.c:268
static int reload ( void  )
static

Definition at line 4799 of file pbx_dundi.c.

References AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, and set_config().

4800 {
4801  struct sockaddr_in sin;
4802 
4803  if (set_config("dundi.conf", &sin, 1))
4804  return AST_MODULE_LOAD_FAILURE;
4805 
4806  return AST_MODULE_LOAD_SUCCESS;
4807 }
static int set_config(char *config_file, struct sockaddr_in *sin, int reload)
Definition: pbx_dundi.c:4621
static void reschedule_precache ( const char *  number,
const char *  context,
int  expiration 
)
static

Definition at line 3689 of file pbx_dundi.c.

References ast_calloc, 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(), and dundi_precache_queue::number.

Referenced by dundi_precache_full(), and dundi_precache_internal().

3690 {
3691  int len;
3692  struct dundi_precache_queue *qe, *prev;
3693 
3694  AST_LIST_LOCK(&pcq);
3696  if (!strcmp(number, qe->number) && !strcasecmp(context, qe->context)) {
3698  break;
3699  }
3700  }
3702  if (!qe) {
3703  len = sizeof(*qe);
3704  len += strlen(number) + 1;
3705  len += strlen(context) + 1;
3706  if (!(qe = ast_calloc(1, len))) {
3707  AST_LIST_UNLOCK(&pcq);
3708  return;
3709  }
3710  strcpy(qe->number, number);
3711  qe->context = qe->number + strlen(number) + 1;
3712  strcpy(qe->context, context);
3713  }
3714  time(&qe->expiration);
3715  qe->expiration += expiration;
3716  if ((prev = AST_LIST_FIRST(&pcq))) {
3717  while (AST_LIST_NEXT(prev, list) && ((AST_LIST_NEXT(prev, list))->expiration <= qe->expiration))
3718  prev = AST_LIST_NEXT(prev, list);
3719  AST_LIST_INSERT_AFTER(&pcq, prev, qe, list);
3720  } else
3721  AST_LIST_INSERT_HEAD(&pcq, qe, list);
3722  AST_LIST_UNLOCK(&pcq);
3723 }
Definition: pbx_dundi.c:333
#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:600
#define AST_LIST_INSERT_AFTER(head, listelm, elm, field)
Inserts a list entry after a given entry.
Definition: linkedlists.h:680
Number structure.
Definition: app_followme.c:109
struct dundi_precache_queue::@312 list
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:554
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:696
#define ast_calloc(a, b)
Definition: astmm.h:82
#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:107
static int rescomp ( const void *  a,
const void *  b 
)
static

Definition at line 2403 of file pbx_dundi.c.

References dundi_result::weight.

Referenced by sort_results().

2404 {
2405  const struct dundi_result *resa, *resb;
2406  resa = a;
2407  resb = b;
2408  if (resa->weight < resb->weight)
2409  return -1;
2410  if (resa->weight > resb->weight)
2411  return 1;
2412  return 0;
2413 }
int weight
Definition: dundi.h:227
static int reset_transaction ( struct dundi_transaction trans)
static

Definition at line 488 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().

489 {
490  int tid;
491  tid = get_trans_id();
492  if (tid < 1)
493  return -1;
494  trans->strans = tid;
495  trans->dtrans = 0;
496  trans->iseqno = 0;
497  trans->oiseqno = 0;
498  trans->oseqno = 0;
499  trans->aseqno = 0;
500  ast_clear_flag(trans, FLAG_FINAL);
501  return 0;
502 }
unsigned char aseqno
Definition: pbx_dundi.c:256
unsigned char oiseqno
Definition: pbx_dundi.c:254
static int get_trans_id(void)
Definition: pbx_dundi.c:469
unsigned short strans
Definition: pbx_dundi.c:251
unsigned char oseqno
Definition: pbx_dundi.c:255
unsigned short dtrans
Definition: pbx_dundi.c:252
#define ast_clear_flag(p, flag)
Definition: utils.h:77
unsigned char iseqno
Definition: pbx_dundi.c:253
static void save_secret ( const char *  newkey,
const char *  oldkey 
)
static

Definition at line 2094 of file pbx_dundi.c.

References ast_db_put(), and DUNDI_SECRET_TIME.

Referenced by check_password(), and load_password().

2095 {
2096  char tmp[256];
2097  if (oldkey)
2098  snprintf(tmp, sizeof(tmp), "%s;%s", oldkey, newkey);
2099  else
2100  snprintf(tmp, sizeof(tmp), "%s", newkey);
2101  rotatetime = time(NULL) + DUNDI_SECRET_TIME;
2102  ast_db_put(secretpath, "secret", tmp);
2103  snprintf(tmp, sizeof(tmp), "%d", (int)rotatetime);
2104  ast_db_put(secretpath, "secretexpiry", tmp);
2105 }
static char secretpath[80]
Definition: pbx_dundi.c:199
#define DUNDI_SECRET_TIME
Definition: pbx_dundi.c:173
static time_t rotatetime
Definition: pbx_dundi.c:202
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: db.c:260
static int set_config ( char *  config_file,
struct sockaddr_in *  sin,
int  reload 
)
static

Definition at line 4621 of file pbx_dundi.c.

References any_peer, ast_category_browse(), ast_config_destroy(), ast_config_load, ast_copy_string(), ast_eid_default, ast_gethostbyname(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), 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_precache_full(), find_peer(), hp, ast_variable::lineno, load_password(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, mark_mappings(), mark_peers(), MAXHOSTNAMELEN, ast_variable::name, ast_variable::next, prune_mappings(), prune_peers(), and ast_variable::value.

Referenced by load_module(), and reload().

4622 {
4623  struct ast_config *cfg;
4624  struct ast_variable *v;
4625  char *cat;
4626  int x;
4627  struct ast_flags config_flags = { 0 };
4628  char hn[MAXHOSTNAMELEN] = "";
4629  struct ast_hostent he;
4630  struct hostent *hp;
4631  struct sockaddr_in sin2;
4632  static int last_port = 0;
4633  int globalpcmodel = 0;
4634  dundi_eid testeid;
4635 
4636  if (!(cfg = ast_config_load(config_file, config_flags)) || cfg == CONFIG_STATUS_FILEINVALID) {
4637  ast_log(LOG_ERROR, "Unable to load config %s\n", config_file);
4638  return -1;
4639  }
4640 
4643  any_peer = NULL;
4644 
4645  ipaddr[0] = '\0';
4646  if (!gethostname(hn, sizeof(hn)-1)) {
4647  hp = ast_gethostbyname(hn, &he);
4648  if (hp) {
4649  memcpy(&sin2.sin_addr, hp->h_addr, sizeof(sin2.sin_addr));
4650  ast_copy_string(ipaddr, ast_inet_ntoa(sin2.sin_addr), sizeof(ipaddr));
4651  } else
4652  ast_log(LOG_WARNING, "Unable to look up host '%s'\n", hn);
4653  } else
4654  ast_log(LOG_WARNING, "Unable to get host name!\n");
4655  AST_LIST_LOCK(&peers);
4656 
4657  memcpy(&global_eid, &ast_eid_default, sizeof(global_eid));
4658 
4659  global_storehistory = 0;
4660  ast_copy_string(secretpath, "dundi", sizeof(secretpath));
4661  v = ast_variable_browse(cfg, "general");
4662  while(v) {
4663  if (!strcasecmp(v->name, "port")){
4664  sin->sin_port = htons(atoi(v->value));
4665  if(last_port==0){
4666  last_port=sin->sin_port;
4667  } else if(sin->sin_port != last_port)
4668  ast_log(LOG_WARNING, "change to port ignored until next asterisk re-start\n");
4669  } else if (!strcasecmp(v->name, "bindaddr")) {
4670  struct hostent *hep;
4671  struct ast_hostent hent;
4672  hep = ast_gethostbyname(v->value, &hent);
4673  if (hep) {
4674  memcpy(&sin->sin_addr, hep->h_addr, sizeof(sin->sin_addr));
4675  } else
4676  ast_log(LOG_WARNING, "Invalid host/IP '%s'\n", v->value);
4677  } else if (!strcasecmp(v->name, "authdebug")) {
4678  authdebug = ast_true(v->value);
4679  } else if (!strcasecmp(v->name, "ttl")) {
4680  if ((sscanf(v->value, "%30d", &x) == 1) && (x > 0) && (x < DUNDI_DEFAULT_TTL)) {
4681  dundi_ttl = x;
4682  } else {
4683  ast_log(LOG_WARNING, "'%s' is not a valid TTL at line %d, must be number from 1 to %d\n",
4684  v->value, v->lineno, DUNDI_DEFAULT_TTL);
4685  }
4686  } else if (!strcasecmp(v->name, "autokill")) {
4687  if (sscanf(v->value, "%30d", &x) == 1) {
4688  if (x >= 0)
4690  else
4691  ast_log(LOG_NOTICE, "Nice try, but autokill has to be >0 or 'yes' or 'no' at line %d\n", v->lineno);
4692  } else if (ast_true(v->value)) {
4694  } else {
4696  }
4697  } else if (!strcasecmp(v->name, "entityid")) {
4698  if (!ast_str_to_eid(&testeid, v->value))
4699  global_eid = testeid;
4700  else
4701  ast_log(LOG_WARNING, "Invalid global endpoint identifier '%s' at line %d\n", v->value, v->lineno);
4702  } else if (!strcasecmp(v->name, "tos")) {
4703  if (ast_str2tos(v->value, &tos))
4704  ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno);
4705  } else if (!strcasecmp(v->name, "department")) {
4706  ast_copy_string(dept, v->value, sizeof(dept));
4707  } else if (!strcasecmp(v->name, "organization")) {
4708  ast_copy_string(org, v->value, sizeof(org));
4709  } else if (!strcasecmp(v->name, "locality")) {
4710  ast_copy_string(locality, v->value, sizeof(locality));
4711  } else if (!strcasecmp(v->name, "stateprov")) {
4712  ast_copy_string(stateprov, v->value, sizeof(stateprov));
4713  } else if (!strcasecmp(v->name, "country")) {
4714  ast_copy_string(country, v->value, sizeof(country));
4715  } else if (!strcasecmp(v->name, "email")) {
4716  ast_copy_string(email, v->value, sizeof(email));
4717  } else if (!strcasecmp(v->name, "phone")) {
4718  ast_copy_string(phone, v->value, sizeof(phone));
4719  } else if (!strcasecmp(v->name, "storehistory")) {
4721  } else if (!strcasecmp(v->name, "cachetime")) {
4722  if ((sscanf(v->value, "%30d", &x) == 1)) {
4723  dundi_cache_time = x;
4724  } else {
4725  ast_log(LOG_WARNING, "'%s' is not a valid cache time at line %d. Using default value '%d'.\n",
4727  }
4728  }
4729  v = v->next;
4730  }
4732  mark_mappings();
4733  v = ast_variable_browse(cfg, "mappings");
4734  while(v) {
4735  build_mapping(v->name, v->value);
4736  v = v->next;
4737  }
4738  prune_mappings();
4739  mark_peers();
4740  cat = ast_category_browse(cfg, NULL);
4741  while(cat) {
4742  if (strcasecmp(cat, "general") && strcasecmp(cat, "mappings")) {
4743  /* Entries */
4744  if (!ast_str_to_eid(&testeid, cat))
4745  build_peer(&testeid, ast_variable_browse(cfg, cat), &globalpcmodel);
4746  else if (!strcasecmp(cat, "*")) {
4747  build_peer(&empty_eid, ast_variable_browse(cfg, cat), &globalpcmodel);
4748  any_peer = find_peer(NULL);
4749  } else
4750  ast_log(LOG_NOTICE, "Ignoring invalid EID entry '%s'\n", cat);
4751  }
4752  cat = ast_category_browse(cfg, cat);
4753  }
4754  prune_peers();
4755  ast_config_destroy(cfg);
4756  load_password();
4757  if (globalpcmodel & DUNDI_MODEL_OUTBOUND)
4759  return 0;
4760 }
static void dundi_precache_full(void)
Definition: pbx_dundi.c:3725
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
static const char config_file[]
Definition: cdr_odbc.c:49
static void prune_mappings(void)
Definition: pbx_dundi.c:4168
static char locality[80]
Definition: pbx_dundi.c:194
static unsigned int tos
Definition: chan_h323.c:146
static int dundi_cache_time
Definition: pbx_dundi.c:187
static dundi_eid global_eid
Definition: pbx_dundi.c:189
#define LOG_WARNING
Definition: logger.h:144
#define DUNDI_DEFAULT_CACHE_TIME
Definition: dundi.h:218
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
Definition: config.c:597
int lineno
Definition: config.h:87
static char email[80]
Definition: pbx_dundi.c:197
static char phone[80]
Definition: pbx_dundi.c:198
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
#define MAXHOSTNAMELEN
Definition: network.h:69
int ast_str2tos(const char *value, unsigned int *tos)
Convert a string to the appropriate TOS value.
Definition: acl.c:667
static void load_password(void)
Definition: pbx_dundi.c:2107
An Entity ID is essentially a MAC address, brief and unique.
Definition: utils.h:808
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
static int authdebug
Definition: pbx_dundi.c:184
static char secretpath[80]
Definition: pbx_dundi.c:199
const char * value
Definition: config.h:79
static struct dundi_peer * any_peer
Wildcard peer.
Definition: pbx_dundi.c:343
#define DUNDI_DEFAULT_TTL
Definition: dundi.h:216
#define ast_config_load(filename, flags)
Load a config file.
Definition: config.h:170
char * ast_category_browse(struct ast_config *config, const char *prev)
Goes through categories.
Definition: config.c:810
static int global_storehistory
Definition: pbx_dundi.c:191
int ast_str_to_eid(struct ast_eid *eid, const char *s)
Convert a string into an EID.
Definition: netsock.c:305
static dundi_eid empty_eid
Definition: pbx_dundi.c:203
const char * name
Definition: config.h:77
static char ipaddr[80]
Definition: pbx_dundi.c:201
#define LOG_ERROR
Definition: logger.h:155
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
static struct dundi_peer * find_peer(dundi_eid *eid)
Definition: pbx_dundi.c:504
static char country[80]
Definition: pbx_dundi.c:196
static int global_autokilltimeout
Definition: pbx_dundi.c:188
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
#define DEFAULT_MAXMS
Definition: chan_iax2.c:343
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: utils.c:564
static int dundi_ttl
Definition: pbx_dundi.c:185
Structure used to handle boolean flags.
Definition: utils.h:200
struct ast_eid ast_eid_default
Global EID.
Definition: asterisk.c:192
struct hostent * ast_gethostbyname(const char *host, struct ast_hostent *hp)
Thread-safe gethostbyname function to use in Asterisk.
Definition: utils.c:195
static void mark_peers(void)
Definition: pbx_dundi.c:4106
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static void build_peer(dundi_eid *eid, struct ast_variable *v, int *globalpcmode)
Definition: pbx_dundi.c:4353
static char org[80]
Definition: pbx_dundi.c:193
static void mark_mappings(void)
Definition: pbx_dundi.c:4116
struct ast_variable * next
Definition: config.h:82
static void build_mapping(const char *name, const char *value)
Definition: pbx_dundi.c:4198
#define CONFIG_STATUS_FILEINVALID
Definition: config.h:52
static struct hostent * hp
Definition: chan_skinny.c:1048
#define DUNDI_MODEL_OUTBOUND
Definition: pbx_dundi.c:152
static void prune_peers(void)
Definition: pbx_dundi.c:4153
static char dept[80]
Definition: pbx_dundi.c:192
static char stateprov[80]
Definition: pbx_dundi.c:195
static int socket_read ( int *  id,
int  fd,
short  events,
void *  cbdata 
)
static

Definition at line 2051 of file pbx_dundi.c.

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

Referenced by network_thread().

2052 {
2053  struct sockaddr_in sin;
2054  int res;
2055  struct dundi_hdr *h;
2056  char buf[MAX_PACKET_SIZE];
2057  socklen_t len = sizeof(sin);
2058 
2059  res = recvfrom(netsocket, buf, sizeof(buf) - 1, 0,(struct sockaddr *) &sin, &len);
2060  if (res < 0) {
2061  if (errno != ECONNREFUSED)
2062  ast_log(LOG_WARNING, "Error: %s\n", strerror(errno));
2063  return 1;
2064  }
2065  if (res < sizeof(struct dundi_hdr)) {
2066  ast_log(LOG_WARNING, "midget packet received (%d of %d min)\n", res, (int)sizeof(struct dundi_hdr));
2067  return 1;
2068  }
2069  buf[res] = '\0';
2070  h = (struct dundi_hdr *) buf;
2071  if (dundidebug)
2072  dundi_showframe(h, 1, &sin, res - sizeof(struct dundi_hdr));
2073  AST_LIST_LOCK(&peers);
2074  handle_frame(h, &sin, res - sizeof(struct dundi_hdr));
2076  return 1;
2077 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define LOG_WARNING
Definition: logger.h:144
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static int netsocket
Definition: pbx_dundi.c:178
static int dundidebug
Definition: pbx_dundi.c:183
void dundi_showframe(struct dundi_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen)
Definition: dundi-parser.c:433
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int errno
#define MAX_PACKET_SIZE
Definition: pbx_dundi.c:147
static int handle_frame(struct dundi_hdr *h, struct sockaddr_in *sin, int datalen)
Definition: pbx_dundi.c:2010
static void sort_results ( struct dundi_result results,
int  count 
)
static

Definition at line 2415 of file pbx_dundi.c.

References rescomp().

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

2416 {
2417  qsort(results, count, sizeof(results[0]), rescomp);
2418 }
static int rescomp(const void *a, const void *b)
Definition: pbx_dundi.c:2403
static int start_network_thread ( void  )
static

Definition at line 2261 of file pbx_dundi.c.

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

Referenced by load_module().

2262 {
2266  return 0;
2267 }
static pthread_t precachethreadid
Definition: pbx_dundi.c:180
static void * process_precache(void *ign)
Definition: pbx_dundi.c:2224
static void * network_thread(void *ignore)
Definition: pbx_dundi.c:2163
static pthread_t netthreadid
Definition: pbx_dundi.c:179
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:426
static pthread_t clearcachethreadid
Definition: pbx_dundi.c:181
static void * process_clearcache(void *ignore)
Definition: pbx_dundi.c:2190
static int str2tech ( char *  str)
static

Definition at line 387 of file pbx_dundi.c.

References DUNDI_PROTO_H323, DUNDI_PROTO_IAX, and DUNDI_PROTO_SIP.

Referenced by build_mapping().

388 {
389  if (!strcasecmp(str, "IAX") || !strcasecmp(str, "IAX2"))
390  return DUNDI_PROTO_IAX;
391  else if (!strcasecmp(str, "SIP"))
392  return DUNDI_PROTO_SIP;
393  else if (!strcasecmp(str, "H323"))
394  return DUNDI_PROTO_H323;
395  else
396  return -1;
397 }
const char * str
Definition: app_jack.c:144
static char* tech2str ( int  tech)
static

Definition at line 371 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_mappings(), and handle_command_response().

372 {
373  switch(tech) {
374  case DUNDI_PROTO_NONE:
375  return "None";
376  case DUNDI_PROTO_IAX:
377  return "IAX2";
378  case DUNDI_PROTO_SIP:
379  return "SIP";
380  case DUNDI_PROTO_H323:
381  return "H323";
382  default:
383  return "Unknown";
384  }
385 }
static int unload_module ( void  )
static

Definition at line 4762 of file pbx_dundi.c.

References ARRAY_LEN, ast_cli_unregister_multiple(), ast_custom_function_unregister(), AST_PTHREADT_NULL, ast_unregister_switch(), clearcachethreadid, io_context_destroy(), mark_mappings(), mark_peers(), netthreadid, precachethreadid, prune_mappings(), prune_peers(), and sched_context_destroy().

4763 {
4764  pthread_t previous_netthreadid = netthreadid, previous_precachethreadid = precachethreadid, previous_clearcachethreadid = clearcachethreadid;
4765 
4771 
4772  /* Stop all currently running threads */
4773  dundi_shutdown = 1;
4774  if (previous_netthreadid != AST_PTHREADT_NULL) {
4775  pthread_kill(previous_netthreadid, SIGURG);
4776  pthread_join(previous_netthreadid, NULL);
4777  }
4778  if (previous_precachethreadid != AST_PTHREADT_NULL) {
4779  pthread_kill(previous_precachethreadid, SIGURG);
4780  pthread_join(previous_precachethreadid, NULL);
4781  }
4782  if (previous_clearcachethreadid != AST_PTHREADT_NULL) {
4783  pthread_cancel(previous_clearcachethreadid);
4784  pthread_join(previous_clearcachethreadid, NULL);
4785  }
4786 
4787  close(netsocket);
4790 
4791  mark_mappings();
4792  prune_mappings();
4793  mark_peers();
4794  prune_peers();
4795 
4796  return 0;
4797 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static void prune_mappings(void)
Definition: pbx_dundi.c:4168
static pthread_t precachethreadid
Definition: pbx_dundi.c:180
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: cli.c:2177
static struct io_context * io
Definition: pbx_dundi.c:176
Definition: sched.c:57
void ast_unregister_switch(struct ast_switch *sw)
Unregister an alternative switch.
Definition: pbx.c:6457
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
Definition: pbx.c:3814
static pthread_t netthreadid
Definition: pbx_dundi.c:179
static int netsocket
Definition: pbx_dundi.c:178
void io_context_destroy(struct io_context *ioc)
Destroys a context.
Definition: io.c:102
#define AST_PTHREADT_NULL
Definition: lock.h:65
static struct ast_custom_function dundi_function
Definition: pbx_dundi.c:3939
void sched_context_destroy(struct sched_context *c)
destroys a schedule context Destroys (free&#39;s) the given sched_context structure
Definition: sched.c:267
static pthread_t clearcachethreadid
Definition: pbx_dundi.c:181
static struct ast_cli_entry cli_dundi[]
Definition: pbx_dundi.c:2884
static int dundi_shutdown
Definition: pbx_dundi.c:204
static void mark_peers(void)
Definition: pbx_dundi.c:4106
static void mark_mappings(void)
Definition: pbx_dundi.c:4116
static struct ast_custom_function dundi_query_function
Definition: pbx_dundi.c:4027
static struct ast_switch dundi_switch
Definition: pbx_dundi.c:4612
static void prune_peers(void)
Definition: pbx_dundi.c:4153
static struct ast_custom_function dundi_result_function
Definition: pbx_dundi.c:4101
static void unregister_request ( struct dundi_request dr)
static

Definition at line 3540 of file pbx_dundi.c.

References AST_LIST_LOCK, AST_LIST_REMOVE, and AST_LIST_UNLOCK.

Referenced by dundi_lookup_internal().

3541 {
3542  AST_LIST_LOCK(&peers);
3543  AST_LIST_REMOVE(&requests, dr, list);
3545 }
#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:841
static int update_key ( struct dundi_peer peer)
static

Definition at line 1312 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, 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().

1313 {
1314  unsigned char key[16];
1315  struct ast_key *ekey, *skey;
1316  char eid_str[20];
1317  int res;
1318  if (!peer->keyexpire || (peer->keyexpire < time(NULL))) {
1319  build_iv(key);
1320  ast_aes_set_encrypt_key(key, &peer->us_ecx);
1321  ast_aes_set_decrypt_key(key, &peer->us_dcx);
1322  ekey = ast_key_get(peer->inkey, AST_KEY_PUBLIC);
1323  if (!ekey) {
1324  ast_log(LOG_NOTICE, "No such key '%s' for creating RSA encrypted shared key for '%s'!\n",
1325  peer->inkey, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
1326  return -1;
1327  }
1328  skey = ast_key_get(peer->outkey, AST_KEY_PRIVATE);
1329  if (!skey) {
1330  ast_log(LOG_NOTICE, "No such key '%s' for signing RSA encrypted shared key for '%s'!\n",
1331  peer->outkey, ast_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
1332  return -1;
1333  }
1334  if ((res = ast_encrypt_bin(peer->txenckey, key, sizeof(key), ekey)) != 128) {
1335  ast_log(LOG_NOTICE, "Whoa, got a weird encrypt size (%d != %d)!\n", res, 128);
1336  return -1;
1337  }
1338  if ((res = ast_sign_bin(skey, (char *)peer->txenckey, 128, peer->txenckey + 128))) {
1339  ast_log(LOG_NOTICE, "Failed to sign key (%d)!\n", res);
1340  return -1;
1341  }
1342  peer->us_keycrc32 = crc32(0L, peer->txenckey, 128);
1343  peer->sentfullkey = 0;
1344  /* Looks good */
1345  time(&peer->keyexpire);
1346  peer->keyexpire += dundi_key_ttl;
1347  }
1348  return 0;
1349 }
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Definition: netsock.c:222
int ast_aes_set_encrypt_key(const unsigned char *key, ast_aes_encrypt_key *ctx)
Set an encryption key.
Definition: res_crypto.c:461
static int dundi_key_ttl
Definition: pbx_dundi.c:186
char outkey[80]
Definition: pbx_dundi.c:301
time_t keyexpire
Definition: pbx_dundi.c:315
uint32_t us_keycrc32
Definition: pbx_dundi.c:309
int ast_encrypt_bin(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key)
Encrypt a message using a given private key.
Definition: res_crypto.c:363
int ast_sign_bin(struct ast_key *key, const char *msg, int msglen, unsigned char *sig)
Sign a message signature using a given private key.
Definition: res_crypto.c:299
ast_aes_decrypt_key us_dcx
Definition: pbx_dundi.c:311
static void build_iv(unsigned char *iv)
Definition: pbx_dundi.c:522
#define AST_KEY_PRIVATE
Definition: crypto.h:43
int ast_aes_set_decrypt_key(const unsigned char *key, ast_aes_decrypt_key *ctx)
Set a decryption key.
Definition: res_crypto.c:466
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
dundi_eid eid
Definition: pbx_dundi.c:295
char inkey[80]
Definition: pbx_dundi.c:300
ast_aes_encrypt_key us_ecx
Definition: pbx_dundi.c:310
unsigned char txenckey[256]
Definition: pbx_dundi.c:307
#define AST_KEY_PUBLIC
Definition: crypto.h:42
struct ast_key * ast_key_get(const char *key, int type)
Retrieve a key.
Definition: res_crypto.c:136
int sentfullkey
Definition: pbx_dundi.c:305

Variable Documentation

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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, .nonoptreq = "res_crypto", }
static

Definition at line 4867 of file pbx_dundi.c.

struct alltrans alltrans = { .first = NULL, .last = NULL, }
static
struct dundi_peer* any_peer
static

Wildcard peer.

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

Definition at line 343 of file pbx_dundi.c.

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

Definition at line 4867 of file pbx_dundi.c.

int authdebug = 0
static

Definition at line 184 of file pbx_dundi.c.

pthread_t clearcachethreadid = AST_PTHREADT_NULL
static

Definition at line 181 of file pbx_dundi.c.

Referenced by unload_module().

struct ast_cli_entry cli_dundi[]
static

Definition at line 2884 of file pbx_dundi.c.

char country[80]
static

Definition at line 196 of file pbx_dundi.c.

Referenced by load_indications(), and SendDialTone().

char cursecret[80]
static

Definition at line 200 of file pbx_dundi.c.

int default_expiration = 60
static

Definition at line 190 of file pbx_dundi.c.

Referenced by handle_command_response().

char dept[80]
static

Definition at line 192 of file pbx_dundi.c.

int dundi_key_ttl = DUNDI_DEFAULT_KEY_EXPIRE
static

Definition at line 186 of file pbx_dundi.c.

Referenced by update_key().

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:3968

Definition at line 4027 of file pbx_dundi.c.

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

Definition at line 3888 of file pbx_dundi.c.

Referenced by dundi_query_read(), and dundifunc_read().

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:3957

Definition at line 3963 of file pbx_dundi.c.

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:4032

Definition at line 4101 of file pbx_dundi.c.

unsigned int dundi_result_id
static

Definition at line 3944 of file pbx_dundi.c.

int dundi_shutdown = 0
static

Definition at line 204 of file pbx_dundi.c.

struct ast_switch dundi_switch
static

Definition at line 4612 of file pbx_dundi.c.

int dundi_ttl = DUNDI_DEFAULT_TTL
static

Definition at line 185 of file pbx_dundi.c.

int dundidebug = 0
static

Definition at line 183 of file pbx_dundi.c.

char email[80]
static

Definition at line 197 of file pbx_dundi.c.

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

Definition at line 203 of file pbx_dundi.c.

Referenced by find_peer().

int global_autokilltimeout = 0
static

Definition at line 188 of file pbx_dundi.c.

Referenced by apply_peer().

dundi_eid global_eid
static

Definition at line 189 of file pbx_dundi.c.

Referenced by build_peer().

int global_storehistory = 0
static

Definition at line 191 of file pbx_dundi.c.

struct io_context* io
static

Definition at line 176 of file pbx_dundi.c.

char ipaddr[80]
static

Definition at line 201 of file pbx_dundi.c.

Referenced by realtime_peer(), and realtime_update_peer().

char locality[80]
static

Definition at line 194 of file pbx_dundi.c.

struct mappings mappings = { .first = NULL, .last = NULL, }
static
int netsocket = -1
static

Definition at line 178 of file pbx_dundi.c.

Referenced by ast_netsock_bindaddr(), and handle_error().

pthread_t netthreadid = AST_PTHREADT_NULL
static

Definition at line 179 of file pbx_dundi.c.

Referenced by unload_module().

char org[80]
static

Definition at line 193 of file pbx_dundi.c.

Referenced by calc_crc().

struct pcq pcq = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } , }
static
struct peers peers = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } , }
static
char phone[80]
static

Definition at line 198 of file pbx_dundi.c.

Referenced by privacy_exec().

pthread_t precachethreadid = AST_PTHREADT_NULL
static

Definition at line 180 of file pbx_dundi.c.

Referenced by unload_module().

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

Referenced by ast_aoc_create().

time_t rotatetime
static

Definition at line 202 of file pbx_dundi.c.

struct sched_context* sched
static

Definition at line 177 of file pbx_dundi.c.

char secretpath[80]
static

Definition at line 199 of file pbx_dundi.c.

char stateprov[80]
static

Definition at line 195 of file pbx_dundi.c.

unsigned int tos = 0
static

Definition at line 182 of file pbx_dundi.c.