Convert the PBX core to use read/write locks. This yields a nifty performance improve...
[asterisk/asterisk.git] / pbx / pbx_dundi.c
old mode 100755 (executable)
new mode 100644 (file)
index d0cab9c..62c2c55
@@ -1,45 +1,44 @@
 /*
- * Distributed Universal Number Discovery (DUNDi)
+ * Asterisk -- An open source telephony toolkit.
  *
- * Copyright (C) 2004, Digium Inc.
+ * Copyright (C) 1999 - 2006, Digium, Inc.
  *
- * Written by Mark Spencer <markster@digium.com>
+ * Mark Spencer <markster@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Distributed Universal Number Discovery (DUNDi)
  *
- * This program is Free Software distributed under the terms of
- * of the GNU General Public License.
  */
 
-#include <asterisk/file.h>
-#include <asterisk/logger.h>
-#include <asterisk/channel.h>
-#include <asterisk/config.h>
-#include <asterisk/options.h>
-#include <asterisk/pbx.h>
-#include <asterisk/module.h>
-#include <asterisk/frame.h>
-#include <asterisk/file.h>
-#include <asterisk/channel_pvt.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/crypto.h>
-#include <asterisk/astdb.h>
-#include <asterisk/acl.h>
-#include <asterisk/aes.h>
+/*** MODULEINFO
+       <depend>zlib</depend>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
-#include "dundi-parser.h"
 #include <stdlib.h>
+#include <stdio.h>
 #include <unistd.h>
-#include <arpa/inet.h>
 #include <netinet/in.h>
+#include <arpa/inet.h>
 #include <sys/socket.h>
 #include <string.h>
 #include <errno.h>
-#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(SOLARIS) || defined(__OSX__)
+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(SOLARIS) || defined(__Darwin__)
 #include <sys/types.h>
 #include <netinet/in_systm.h>
 #endif
 #include <sys/ioctl.h>
 #include <netinet/in.h>
 #include <net/if.h>
-#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OSX__)
+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__Darwin__)
 #include <net/if_dl.h>
 #include <ifaddrs.h>
 #endif
 #include <zlib.h>
 
-#define MAX_RESULTS    64
+#include "asterisk/file.h"
+#include "asterisk/logger.h"
+#include "asterisk/channel.h"
+#include "asterisk/config.h"
+#include "asterisk/options.h"
+#include "asterisk/pbx.h"
+#include "asterisk/module.h"
+#include "asterisk/frame.h"
+#include "asterisk/file.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/crypto.h"
+#include "asterisk/astdb.h"
+#include "asterisk/acl.h"
+#include "asterisk/aes.h"
 
-#define MAX_PACKET_SIZE 8192
-
-extern char ast_config_AST_KEY_DIR[];
+#include "dundi-parser.h"
 
-static char *tdesc = "Distributed Universal Number Discovery (DUNDi)";
+#define MAX_RESULTS    64
 
-static char *app = "DUNDiLookup";
-static char *synopsis = "Look up a number with DUNDi";
-static char *descrip = 
-"DUNDiLookup(number[|context[|options]])\n"
-"      Looks up a given number in the global context specified or in\n"
-"the reserved 'e164' context if not specified.  Returns -1 if the channel\n"
-"is hungup during the lookup or 0 otherwise.  On completion, the variable\n"
-"${DUNDTECH} and ${DUNDDEST} will contain the technology and destination\n"
-"of the appropriate technology and destination to access the number. If no\n"
-"answer was found, and the priority n + 101 exists, execution will continue\n"
-"at that location.\n";
+#define MAX_PACKET_SIZE 8192
 
 #define DUNDI_MODEL_INBOUND            (1 << 0)
 #define DUNDI_MODEL_OUTBOUND   (1 << 1)
 #define DUNDI_MODEL_SYMMETRIC  (DUNDI_MODEL_INBOUND | DUNDI_MODEL_OUTBOUND)
 
-/* Keep times of last 10 lookups */
+/*! Keep times of last 10 lookups */
 #define DUNDI_TIMING_HISTORY   10
 
-#define FLAG_ISREG             (1 << 0)                /* Transaction is register request */
-#define FLAG_DEAD              (1 << 1)                /* Transaction is dead */
-#define FLAG_FINAL             (1 << 2)                /* Transaction has final message sent */
-#define FLAG_ISQUAL            (1 << 3)                /* Transaction is a qualification */
-#define FLAG_ENCRYPT   (1 << 4)                /* Transaction is encrypted wiht ECX/DCX */
-#define FLAG_SENDFULLKEY       (1 << 5)                /* Send full key on transaction */
-#define FLAG_STOREHIST (1 << 6)                /* Record historic performance */
+enum {
+       FLAG_ISREG =       (1 << 0),  /*!< Transaction is register request */
+       FLAG_DEAD =        (1 << 1),  /*!< Transaction is dead */
+       FLAG_FINAL =       (1 << 2),  /*!< Transaction has final message sent */
+       FLAG_ISQUAL =      (1 << 3),  /*!< Transaction is a qualification */
+       FLAG_ENCRYPT =     (1 << 4),  /*!< Transaction is encrypted wiht ECX/DCX */
+       FLAG_SENDFULLKEY = (1 << 5),  /*!< Send full key on transaction */
+       FLAG_STOREHIST =   (1 << 6),  /*!< Record historic performance */
+};
 
 #define DUNDI_FLAG_INTERNAL_NOPARTIAL (1 << 17)
 
@@ -96,9 +104,6 @@ static char *descrip =
 #define DUNDI_SECRET_TIME DUNDI_DEFAULT_CACHE_TIME
 #endif
 
-#define KEY_OUT                        0
-#define KEY_IN                 1
-
 static struct io_context *io;
 static struct sched_context *sched;
 static int netsocket = -1;
@@ -109,6 +114,7 @@ static int dundidebug = 0;
 static int authdebug = 0;
 static int dundi_ttl = DUNDI_DEFAULT_TTL;
 static int dundi_key_ttl = DUNDI_DEFAULT_KEY_EXPIRE;
+static int dundi_cache_time = DUNDI_DEFAULT_CACHE_TIME;
 static int global_autokilltimeout = 0;
 static dundi_eid global_eid;
 static int default_expiration = 60;
@@ -125,15 +131,16 @@ static char cursecret[80];
 static char ipaddr[80];
 static time_t rotatetime;
 static dundi_eid empty_eid = { { 0, 0, 0, 0, 0, 0 } };
+
 struct permission {
-       struct permission *next;
+       AST_LIST_ENTRY(permission) list;
        int allow;
        char name[0];
 };
 
 struct dundi_packet {
+       AST_LIST_ENTRY(dundi_packet) list;
        struct dundi_hdr *h;
-       struct dundi_packet *next;
        int datalen;
        struct dundi_transaction *parent;
        int retransid;
@@ -147,7 +154,7 @@ struct dundi_hint_metadata {
 };
 
 struct dundi_precache_queue {
-       struct dundi_precache_queue *next;
+       AST_LIST_ENTRY(dundi_precache_queue) list;
        char *context;
        time_t expiration;
        char number[0];
@@ -156,32 +163,32 @@ struct dundi_precache_queue {
 struct dundi_request;
 
 struct dundi_transaction {
-       struct sockaddr_in addr;        /* Other end of transaction */
-       struct timeval start;           /* When this transaction was created */
+       struct sockaddr_in addr;                       /*!< Other end of transaction */
+       struct timeval start;                          /*!< When this transaction was created */
        dundi_eid eids[DUNDI_MAX_STACK + 1];
-       int eidcount;                           /* Number of eids in eids */
-       dundi_eid us_eid;                       /* Our EID, to them */
-       dundi_eid them_eid;                     /* Their EID, to us */
-       aes_encrypt_ctx ecx;            /* AES 128 Encryption context */
-       aes_decrypt_ctx dcx;            /* AES 128 Decryption context */
-       int flags;                                      /* Has final packet been sent */
-       int ttl;                                        /* Remaining TTL for queries on this one */
-       int thread;                                     /* We have a calling thread */
-       int retranstimer;                       /* How long to wait before retransmissions */
-       int autokillid;                         /* ID to kill connection if answer doesn't come back fast enough */
-       int autokilltimeout;            /* Recommended timeout for autokill */
-       unsigned short strans;          /* Our transaction identifier */
-       unsigned short dtrans;          /* Their transaction identifer */
-       unsigned char iseqno;           /* Next expected received seqno */
-       unsigned char oiseqno;          /* Last received incoming seqno */
-       unsigned char oseqno;           /* Next transmitted seqno */
-       unsigned char aseqno;           /* Last acknowledge seqno */
-       struct dundi_packet *packets;   /* Packets to be retransmitted */
-       struct dundi_packet *lasttrans; /* Last transmitted / ACK'd packet */
-       struct dundi_transaction *next; /* Next with respect to the parent */
-       struct dundi_request *parent;   /* Parent request (if there is one) */
-       struct dundi_transaction *allnext; /* Next with respect to all DUNDi transactions */
-} *alltrans;
+       int eidcount;                                  /*!< Number of eids in eids */
+       dundi_eid us_eid;                              /*!< Our EID, to them */
+       dundi_eid them_eid;                            /*!< Their EID, to us */
+       aes_encrypt_ctx ecx;                           /*!< AES 128 Encryption context */
+       aes_decrypt_ctx dcx;                           /*!< AES 128 Decryption context */
+       unsigned int flags;                            /*!< Has final packet been sent */
+       int ttl;                                       /*!< Remaining TTL for queries on this one */
+       int thread;                                    /*!< We have a calling thread */
+       int retranstimer;                              /*!< How long to wait before retransmissions */
+       int autokillid;                                /*!< ID to kill connection if answer doesn't come back fast enough */
+       int autokilltimeout;                           /*!< Recommended timeout for autokill */
+       unsigned short strans;                         /*!< Our transaction identifier */
+       unsigned short dtrans;                         /*!< Their transaction identifer */
+       unsigned char iseqno;                          /*!< Next expected received seqno */
+       unsigned char oiseqno;                         /*!< Last received incoming seqno */
+       unsigned char oseqno;                          /*!< Next transmitted seqno */
+       unsigned char aseqno;                          /*!< Last acknowledge seqno */
+       AST_LIST_HEAD_NOLOCK(packetlist, dundi_packet) packets;  /*!< Packets to be retransmitted */
+       struct packetlist lasttrans;                   /*!< Last transmitted / ACK'd packet */
+       struct dundi_request *parent;                  /*!< Parent request (if there is one) */
+       AST_LIST_ENTRY(dundi_transaction) parentlist;  /*!< Next with respect to the parent */
+       AST_LIST_ENTRY(dundi_transaction) all;         /*!< Next with respect to all DUNDi transactions */
+};
 
 struct dundi_request {
        char dcontext[AST_MAX_EXTENSION];
@@ -196,12 +203,12 @@ struct dundi_request {
        int expiration;
        int cbypass;
        int pfds[2];
-       unsigned long crc32;                                                    /* CRC-32 of all but root EID's in avoid list */
-       struct dundi_transaction *trans;        /* Transactions */
-       struct dundi_request *next;
-} *requests;
+       unsigned long crc32;                              /*!< CRC-32 of all but root EID's in avoid list */
+       AST_LIST_HEAD_NOLOCK(, dundi_transaction) trans;  /*!< Transactions */
+       AST_LIST_ENTRY(dundi_request) list;
+};
 
-static struct dundi_mapping {
+struct dundi_mapping {
        char dcontext[AST_MAX_EXTENSION];
        char lcontext[AST_MAX_EXTENSION];
        int weight;
@@ -209,16 +216,14 @@ static struct dundi_mapping {
        int tech;
        int dead;
        char dest[AST_MAX_EXTENSION];
-       struct dundi_mapping *next;
-} *mappings = NULL;
+       AST_LIST_ENTRY(dundi_mapping) list;
+};
 
-static struct dundi_peer {
+struct dundi_peer {
        dundi_eid eid;
-       struct sockaddr_in addr;        /* Address of DUNDi peer */
-       struct permission *permit;
-       struct permission *include;
-       struct permission *precachesend;
-       struct permission *precachereceive;
+       struct sockaddr_in addr;               /*!< Address of DUNDi peer */
+       AST_LIST_HEAD_NOLOCK(permissionlist, permission) permit;
+       struct permissionlist include;
        dundi_eid us_eid;
        char inkey[80];
        char outkey[80];
@@ -227,35 +232,35 @@ static struct dundi_peer {
        int qualifyid;
        int sentfullkey;
        int order;
-       unsigned char txenckey[256]; /* Transmitted encrypted key + sig */
-       unsigned char rxenckey[256]; /* Cache received encrypted key + sig */
-       unsigned long us_keycrc32;      /* CRC-32 of our key */
-       aes_encrypt_ctx us_ecx;         /* Cached AES 128 Encryption context */
-       aes_decrypt_ctx us_dcx;         /* Cached AES 128 Decryption context */
-       unsigned long them_keycrc32;/* CRC-32 of our key */
-       aes_encrypt_ctx them_ecx;       /* Cached AES 128 Encryption context */
-       aes_decrypt_ctx them_dcx;       /* Cached AES 128 Decryption context */
-       time_t keyexpire;                       /* When to expire/recreate key */
+       unsigned char txenckey[256];           /*!< Transmitted encrypted key + sig */
+       unsigned char rxenckey[256];           /*!< Cache received encrypted key + sig */
+       unsigned long us_keycrc32;             /*!< CRC-32 of our key */
+       aes_encrypt_ctx us_ecx;                /*!< Cached AES 128 Encryption context */
+       aes_decrypt_ctx us_dcx;                /*!< Cached AES 128 Decryption context */
+       unsigned long them_keycrc32;           /*!< CRC-32 of our key */
+       aes_encrypt_ctx them_ecx;              /*!< Cached AES 128 Encryption context */
+       aes_decrypt_ctx them_dcx;              /*!< Cached AES 128 Decryption context */
+       time_t keyexpire;                      /*!< When to expire/recreate key */
        int registerexpire;
        int lookuptimes[DUNDI_TIMING_HISTORY];
        char *lookups[DUNDI_TIMING_HISTORY];
        int avgms;
-       struct dundi_transaction *regtrans;     /* Registration transaction */
-       struct dundi_transaction *qualtrans;    /* Qualify transaction */
-       struct dundi_transaction *keypending;
-       int model;                                      /* Pull model */
-       int pcmodel;                            /* Push/precache model */
-       int dynamic;                            /* Are we dynamic? */
-       int lastms;                                     /* Last measured latency */
-       int maxms;                                      /* Max permissible latency */
-       struct timeval qualtx;          /* Time of transmit */
-       struct dundi_peer *next;
-} *peers;
-
-static struct dundi_precache_queue *pcq;
-
-AST_MUTEX_DEFINE_STATIC(peerlock);
-AST_MUTEX_DEFINE_STATIC(pclock);
+       struct dundi_transaction *regtrans;    /*!< Registration transaction */
+       struct dundi_transaction *qualtrans;   /*!< Qualify transaction */
+       int model;                             /*!< Pull model */
+       int pcmodel;                           /*!< Push/precache model */
+       int dynamic;                           /*!< Are we dynamic? */
+       int lastms;                            /*!< Last measured latency */
+       int maxms;                             /*!< Max permissible latency */
+       struct timeval qualtx;                 /*!< Time of transmit */
+       AST_LIST_ENTRY(dundi_peer) list;
+};
+
+static AST_LIST_HEAD_STATIC(peers, dundi_peer);
+static AST_LIST_HEAD_STATIC(pcq, dundi_precache_queue);
+static AST_LIST_HEAD_NOLOCK_STATIC(mappings, dundi_mapping);
+static AST_LIST_HEAD_NOLOCK_STATIC(requests, dundi_request);
+static AST_LIST_HEAD_NOLOCK_STATIC(alltrans, dundi_transaction);
 
 static int dundi_xmit(struct dundi_packet *pack);
 
@@ -270,14 +275,16 @@ static void dundi_error_output(const char *data)
        ast_log(LOG_WARNING, "%s", data);
 }
 
-static int has_permission(struct permission *ps, char *cont)
+static int has_permission(struct permissionlist *permlist, char *cont)
 {
-       int res=0;
-       while(ps) {
-               if (!strcasecmp(ps->name, "all") || !strcasecmp(ps->name, cont))
-                       res = ps->allow;
-               ps = ps->next;
+       struct permission *perm;
+       int res = 0;
+
+       AST_LIST_TRAVERSE(permlist, perm, list) {
+               if (!strcasecmp(perm->name, "all") || !strcasecmp(perm->name, cont))
+                       res = perm->allow;
        }
+
        return res;
 }
 
@@ -314,41 +321,37 @@ static int dundi_precache_internal(const char *context, const char *number, int
 static struct dundi_transaction *create_transaction(struct dundi_peer *p);
 static struct dundi_transaction *find_transaction(struct dundi_hdr *hdr, struct sockaddr_in *sin)
 {
-       /* Look for an exact match first */
        struct dundi_transaction *trans;
-       trans = alltrans;
-       while(trans) {
+
+       /* Look for an exact match first */
+       AST_LIST_TRAVERSE(&alltrans, trans, all) {
                if (!inaddrcmp(&trans->addr, sin) && 
                     ((trans->strans == (ntohs(hdr->dtrans) & 32767)) /* Matches our destination */ ||
                          ((trans->dtrans == (ntohs(hdr->strans) & 32767)) && (!hdr->dtrans))) /* We match their destination */) {
                          if (hdr->strans)
                                  trans->dtrans = ntohs(hdr->strans) & 32767;
-                         break;
+                         return trans;
                }
-               trans = trans->allnext;
        }
-       if (!trans) {
-               switch(hdr->cmdresp & 0x7f) {
-               case DUNDI_COMMAND_DPDISCOVER:
-               case DUNDI_COMMAND_EIDQUERY:
-               case DUNDI_COMMAND_PRECACHERQ:
-               case DUNDI_COMMAND_REGREQ:
-               case DUNDI_COMMAND_NULL:
-               case DUNDI_COMMAND_ENCRYPT:
-                       if (hdr->strans) {      
-                               /* Create new transaction */
-                               trans = create_transaction(NULL);
-                               if (trans) {
-                                       memcpy(&trans->addr, sin, sizeof(trans->addr));
-                                       trans->dtrans = ntohs(hdr->strans) & 32767;
-                               } else
-                                       ast_log(LOG_WARNING, "Out of memory!\n");
-                       }
+       
+       switch(hdr->cmdresp & 0x7f) {
+       case DUNDI_COMMAND_DPDISCOVER:
+       case DUNDI_COMMAND_EIDQUERY:
+       case DUNDI_COMMAND_PRECACHERQ:
+       case DUNDI_COMMAND_REGREQ:
+       case DUNDI_COMMAND_NULL:
+       case DUNDI_COMMAND_ENCRYPT:
+               if (!hdr->strans)
                        break;
-               default:
+               /* Create new transaction */
+               if (!(trans = create_transaction(NULL)))
                        break;
-               }
+               memcpy(&trans->addr, sin, sizeof(trans->addr));
+               trans->dtrans = ntohs(hdr->strans) & 32767;
+       default:
+               break;
        }
+       
        return trans;
 }
 
@@ -386,25 +389,26 @@ static void dundi_reject(struct dundi_hdr *h, struct sockaddr_in *sin)
 static void reset_global_eid(void)
 {
 #if defined(SIOCGIFHWADDR)
-       int x,s;
+       int s, x = 0;
        char eid_str[20];
        struct ifreq ifr;
 
        s = socket(AF_INET, SOCK_STREAM, 0);
-       if (s > 0) {
-               x = 0;
-               for(x=0;x<10;x++) {
-                       memset(&ifr, 0, sizeof(ifr));
-                       snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "eth%d", x);
-                       if (!ioctl(s, SIOCGIFHWADDR, &ifr)) {
-                               memcpy(&global_eid, ((unsigned char *)&ifr.ifr_hwaddr) + 2, sizeof(global_eid));
-                               ast_log(LOG_DEBUG, "Seeding global EID '%s' from '%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &global_eid), ifr.ifr_name);
-                               close(s);
-                               return;
-                       }
-        }
-               close(s);
+       if (s < 0)
+               return;
+       for (x = 0; x < 10; x++) {
+               memset(&ifr, 0, sizeof(ifr));
+               snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "eth%d", x);
+               if (ioctl(s, SIOCGIFHWADDR, &ifr))
+                       continue;
+               memcpy(&global_eid, ((unsigned char *)&ifr.ifr_hwaddr) + 2, sizeof(global_eid));
+               if (option_debug) {
+                       ast_log(LOG_DEBUG, "Seeding global EID '%s' from '%s'\n", 
+                               dundi_eid_to_str(eid_str, sizeof(eid_str), &global_eid), ifr.ifr_name);
+               }
+               break;
        }
+       close(s);
 #else
 #if defined(ifa_broadaddr) && !defined(SOLARIS)
        char eid_str[20];
@@ -418,7 +422,8 @@ static void reset_global_eid(void)
                                memcpy(
                                        &(global_eid.eid),
                                        sdp->sdl_data + sdp->sdl_nlen, 6);
-                               ast_log(LOG_DEBUG, "Seeding global EID '%s' from '%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &global_eid), ifap->ifa_name);
+                               if (option_debug)
+                                       ast_log(LOG_DEBUG, "Seeding global EID '%s' from '%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &global_eid), ifap->ifa_name);
                                freeifaddrs(ifap);
                                return;
                        }
@@ -433,19 +438,19 @@ static void reset_global_eid(void)
 static int get_trans_id(void)
 {
        struct dundi_transaction *t;
-       int stid = (rand() % 32766) + 1;
+       int stid = (ast_random() % 32766) + 1;
        int tid = stid;
+
        do {
-               t = alltrans;
-               while(t) {
+               AST_LIST_TRAVERSE(&alltrans, t, all) {
                        if (t->strans == tid) 
                                break;
-                       t = t->allnext;
                }
                if (!t)
                        return tid;
                tid = (tid % 32766) + 1;
        } while (tid != stid);
+
        return 0;
 }
 
@@ -461,22 +466,23 @@ static int reset_transaction(struct dundi_transaction *trans)
        trans->oiseqno = 0;
        trans->oseqno = 0;
        trans->aseqno = 0;
-       trans->flags &= ~FLAG_FINAL;
+       ast_clear_flag(trans, FLAG_FINAL);      
        return 0;
 }
 
 static struct dundi_peer *find_peer(dundi_eid *eid)
 {
-       struct dundi_peer *cur;
+       struct dundi_peer *cur = NULL;
+
        if (!eid)
                eid = &empty_eid;
-       cur = peers;
-       while(cur) {
+       
+       AST_LIST_TRAVERSE(&peers, cur, list) {
                if (!dundi_eid_cmp(&cur->eid,eid))
-                       return cur;
-               cur = cur->next;
+                       break;
        }
-       return NULL;
+
+       return cur;
 }
 
 static void build_iv(unsigned char *iv)
@@ -486,7 +492,7 @@ static void build_iv(unsigned char *iv)
        int x;
        fluffy = (unsigned int *)(iv);
        for (x=0;x<4;x++)
-               fluffy[x] = rand();
+               fluffy[x] = ast_random();
 }
 
 struct dundi_query_state {
@@ -507,40 +513,39 @@ struct dundi_query_state {
 
 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)
 {
-       int flags;
+       struct ast_flags flags = {0};
        int x;
        if (!ast_strlen_zero(map->lcontext)) {
-               flags = 0;
                if (ast_exists_extension(NULL, map->lcontext, called_number, 1, NULL))
-                       flags |= DUNDI_FLAG_EXISTS;
+                       ast_set_flag(&flags, DUNDI_FLAG_EXISTS);
                if (ast_canmatch_extension(NULL, map->lcontext, called_number, 1, NULL))
-                       flags |= DUNDI_FLAG_CANMATCH;
+                       ast_set_flag(&flags, DUNDI_FLAG_CANMATCH);
                if (ast_matchmore_extension(NULL, map->lcontext, called_number, 1, NULL))
-                       flags |= DUNDI_FLAG_MATCHMORE;
+                       ast_set_flag(&flags, DUNDI_FLAG_MATCHMORE);
                if (ast_ignore_pattern(map->lcontext, called_number))
-                       flags |= DUNDI_FLAG_IGNOREPAT;
+                       ast_set_flag(&flags, DUNDI_FLAG_IGNOREPAT);
 
                /* Clearly we can't say 'don't ask' anymore if we found anything... */
-               if (flags) 
-                       hmd->flags &= ~DUNDI_HINT_DONT_ASK;
+               if (ast_test_flag(&flags, AST_FLAGS_ALL)) 
+                       ast_clear_flag_nonstd(hmd, DUNDI_HINT_DONT_ASK);
 
                if (map->options & DUNDI_FLAG_INTERNAL_NOPARTIAL) {
                        /* Skip partial answers */
-                       flags &= ~(DUNDI_FLAG_MATCHMORE|DUNDI_FLAG_CANMATCH);
+                       ast_clear_flag(&flags, DUNDI_FLAG_MATCHMORE|DUNDI_FLAG_CANMATCH);
                }
-               if (flags) {
+               if (ast_test_flag(&flags, AST_FLAGS_ALL)) {
                        struct varshead headp;
                        struct ast_var_t *newvariable;
-                       flags |= map->options & 0xffff;
-                       dr[anscnt].flags = flags;
+                       ast_set_flag(&flags, map->options & 0xffff);
+                       ast_copy_flags(dr + anscnt, &flags, AST_FLAGS_ALL);
                        dr[anscnt].techint = map->tech;
                        dr[anscnt].weight = map->weight;
-                       dr[anscnt].expiration = DUNDI_DEFAULT_CACHE_TIME;
-                       strncpy(dr[anscnt].tech, tech2str(map->tech), sizeof(dr[anscnt].tech));
+                       dr[anscnt].expiration = dundi_cache_time;
+                       ast_copy_string(dr[anscnt].tech, tech2str(map->tech), sizeof(dr[anscnt].tech));
                        dr[anscnt].eid = *us_eid;
                        dundi_eid_to_str(dr[anscnt].eid_str, sizeof(dr[anscnt].eid_str), &dr[anscnt].eid);
-                       if (flags & DUNDI_FLAG_EXISTS) {
-                               AST_LIST_HEAD_INIT(&headp);
+                       if (ast_test_flag(&flags, DUNDI_FLAG_EXISTS)) {
+                               AST_LIST_HEAD_INIT_NOLOCK(&headp);
                                newvariable = ast_var_assign("NUMBER", called_number);
                                AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
                                newvariable = ast_var_assign("EID", dr[anscnt].eid_str);
@@ -550,17 +555,15 @@ static int dundi_lookup_local(struct dundi_result *dr, struct dundi_mapping *map
                                newvariable = ast_var_assign("IPADDR", ipaddr);
                                AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
                                pbx_substitute_variables_varshead(&headp, map->dest, dr[anscnt].dest, sizeof(dr[anscnt].dest));
-                               while (!AST_LIST_EMPTY(&headp)) {           /* List Deletion. */
-                                       newvariable = AST_LIST_REMOVE_HEAD(&headp, ast_var_t, entries);
+                               while ((newvariable = AST_LIST_REMOVE_HEAD(&headp, entries)))
                                        ast_var_delete(newvariable);
-                               }
                        } else
                                dr[anscnt].dest[0] = '\0';
                        anscnt++;
                } else {
                        /* No answers...  Find the fewest number of digits from the
                           number for which we have no answer. */
-                       char tmp[AST_MAX_EXTENSION]="";
+                       char tmp[AST_MAX_EXTENSION];
                        for (x=0;x<AST_MAX_EXTENSION;x++) {
                                tmp[x] = called_number[x];
                                if (!tmp[x])
@@ -569,7 +572,7 @@ static int dundi_lookup_local(struct dundi_result *dr, struct dundi_mapping *map
                                        /* Oops found something we can't match.  If this is longer
                                           than the running hint, we have to consider it */
                                        if (strlen(tmp) > strlen(hmd->exten)) {
-                                               strncpy(hmd->exten, tmp, sizeof(hmd->exten) - 1);
+                                               ast_copy_string(hmd->exten, tmp, sizeof(hmd->exten));
                                        }
                                        break;
                                }
@@ -591,10 +594,11 @@ static void *dundi_lookup_thread(void *data)
        int res, x;
        int ouranswers=0;
        int max = 999999;
-       int expiration = DUNDI_DEFAULT_CACHE_TIME;
+       int expiration = dundi_cache_time;
 
-       ast_log(LOG_DEBUG, "Whee, looking up '%s@%s' for '%s'\n", st->called_number, st->called_context, 
-               st->eids[0] ? dundi_eid_to_str(eid_str, sizeof(eid_str), st->eids[0]) :  "ourselves");
+       if (option_debug)
+               ast_log(LOG_DEBUG, "Whee, looking up '%s@%s' for '%s'\n", st->called_number, st->called_context, 
+                       st->eids[0] ? dundi_eid_to_str(eid_str, sizeof(eid_str), st->eids[0]) :  "ourselves");
        memset(&ied, 0, sizeof(ied));
        memset(&dr, 0, sizeof(dr));
        memset(&hmd, 0, sizeof(hmd));
@@ -620,12 +624,13 @@ static void *dundi_lookup_thread(void *data)
                                dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_DUPLICATE, "Duplicate Request Pending");
                }
        }
-       ast_mutex_lock(&peerlock);
+       AST_LIST_LOCK(&peers);
        /* Truncate if "don't ask" isn't present */
-       if (!(hmd.flags & DUNDI_HINT_DONT_ASK))
+       if (!ast_test_flag_nonstd(&hmd, DUNDI_HINT_DONT_ASK))
                hmd.exten[0] = '\0';
-       if (st->trans->flags & FLAG_DEAD) {
-               ast_log(LOG_DEBUG, "Our transaction went away!\n");
+       if (ast_test_flag(st->trans, FLAG_DEAD)) {
+               if (option_debug)
+                       ast_log(LOG_DEBUG, "Our transaction went away!\n");
                st->trans->thread = 0;
                destroy_trans(st->trans, 0);
        } else {
@@ -640,7 +645,7 @@ static void *dundi_lookup_thread(void *data)
                dundi_send(st->trans, DUNDI_COMMAND_DPRESPONSE, 0, 1, &ied);
                st->trans->thread = 0;
        }
-       ast_mutex_unlock(&peerlock);
+       AST_LIST_UNLOCK(&peers);
        free(st);
        return NULL;    
 }
@@ -652,37 +657,32 @@ static void *dundi_precache_thread(void *data)
        struct dundi_hint_metadata hmd;
        char eid_str[20];
 
-       ast_log(LOG_DEBUG, "Whee, precaching '%s@%s' for '%s'\n", st->called_number, st->called_context, 
-               st->eids[0] ? dundi_eid_to_str(eid_str, sizeof(eid_str), st->eids[0]) :  "ourselves");
+       if (option_debug)
+               ast_log(LOG_DEBUG, "Whee, precaching '%s@%s' for '%s'\n", st->called_number, st->called_context, 
+                       st->eids[0] ? dundi_eid_to_str(eid_str, sizeof(eid_str), st->eids[0]) :  "ourselves");
        memset(&ied, 0, sizeof(ied));
 
        /* Now produce precache */
        dundi_precache_internal(st->called_context, st->called_number, st->ttl, st->eids);
 
-       ast_mutex_lock(&peerlock);
+       AST_LIST_LOCK(&peers);
        /* Truncate if "don't ask" isn't present */
-       if (!(hmd.flags & DUNDI_HINT_DONT_ASK))
+       if (!ast_test_flag_nonstd(&hmd, DUNDI_HINT_DONT_ASK))
                hmd.exten[0] = '\0';
-       if (st->trans->flags & FLAG_DEAD) {
-               ast_log(LOG_DEBUG, "Our transaction went away!\n");
+       if (ast_test_flag(st->trans, FLAG_DEAD)) {
+               if (option_debug)
+                       ast_log(LOG_DEBUG, "Our transaction went away!\n");
                st->trans->thread = 0;
                destroy_trans(st->trans, 0);
        } else {
                dundi_send(st->trans, DUNDI_COMMAND_PRECACHERP, 0, 1, &ied);
                st->trans->thread = 0;
        }
-       ast_mutex_unlock(&peerlock);
+       AST_LIST_UNLOCK(&peers);
        free(st);
        return NULL;    
 }
 
-static inline int calc_ms(struct timeval *start)
-{
-       struct timeval tv;
-       gettimeofday(&tv, NULL);
-       return ((tv.tv_sec - start->tv_sec) * 1000 + (tv.tv_usec - start->tv_usec) / 1000);
-}
-
 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 void *dundi_query_thread(void *data)
@@ -693,29 +693,33 @@ static void *dundi_query_thread(void *data)
        struct dundi_hint_metadata hmd;
        char eid_str[20];
        int res;
-       ast_log(LOG_DEBUG, "Whee, looking up '%s@%s' for '%s'\n", st->called_number, st->called_context, 
-               st->eids[0] ? dundi_eid_to_str(eid_str, sizeof(eid_str), st->eids[0]) :  "ourselves");
+
+       if (option_debug)
+               ast_log(LOG_DEBUG, "Whee, looking up '%s@%s' for '%s'\n", st->called_number, st->called_context, 
+                       st->eids[0] ? dundi_eid_to_str(eid_str, sizeof(eid_str), st->eids[0]) :  "ourselves");
        memset(&ied, 0, sizeof(ied));
        memset(&dei, 0, sizeof(dei));
        memset(&hmd, 0, sizeof(hmd));
        if (!dundi_eid_cmp(&st->trans->us_eid, &st->reqeid)) {
                /* Ooh, it's us! */
-               ast_log(LOG_DEBUG, "Neat, someone look for us!\n");
-               strncpy(dei.orgunit, dept, sizeof(dei.orgunit));
-               strncpy(dei.org, org, sizeof(dei.org));
-               strncpy(dei.locality, locality, sizeof(dei.locality));
-               strncpy(dei.stateprov, stateprov, sizeof(dei.stateprov));
-               strncpy(dei.country, country, sizeof(dei.country));
-               strncpy(dei.email, email, sizeof(dei.email));
-               strncpy(dei.phone, phone, sizeof(dei.phone));
+               if (option_debug)
+                       ast_log(LOG_DEBUG, "Neat, someone look for us!\n");
+               ast_copy_string(dei.orgunit, dept, sizeof(dei.orgunit));
+               ast_copy_string(dei.org, org, sizeof(dei.org));
+               ast_copy_string(dei.locality, locality, sizeof(dei.locality));
+               ast_copy_string(dei.stateprov, stateprov, sizeof(dei.stateprov));
+               ast_copy_string(dei.country, country, sizeof(dei.country));
+               ast_copy_string(dei.email, email, sizeof(dei.email));
+               ast_copy_string(dei.phone, phone, sizeof(dei.phone));
                res = 1;
        } else {
                /* If we do not have a canonical result, keep looking */
                res = dundi_query_eid_internal(&dei, st->called_context, &st->reqeid, &hmd, st->ttl, 1, st->eids);
        }
-       ast_mutex_lock(&peerlock);
-       if (st->trans->flags & FLAG_DEAD) {
-               ast_log(LOG_DEBUG, "Our transaction went away!\n");
+       AST_LIST_LOCK(&peers);
+       if (ast_test_flag(st->trans, FLAG_DEAD)) {
+               if (option_debug)
+                       ast_log(LOG_DEBUG, "Our transaction went away!\n");
                st->trans->thread = 0;
                destroy_trans(st->trans, 0);
        } else {
@@ -734,7 +738,7 @@ static void *dundi_query_thread(void *data)
                dundi_send(st->trans, DUNDI_COMMAND_EIDRESPONSE, 0, 1, &ied);
                st->trans->thread = 0;
        }
-       ast_mutex_unlock(&peerlock);
+       AST_LIST_UNLOCK(&peers);
        free(st);
        return NULL;    
 }
@@ -760,10 +764,9 @@ static int dundi_answer_entity(struct dundi_transaction *trans, struct dundi_ies
        }
        totallen = sizeof(struct dundi_query_state);
        totallen += (ies->eidcount - skipfirst) * sizeof(dundi_eid);
-       st = malloc(totallen);
+       st = ast_calloc(1, totallen);
        if (st) {
-               memset(st, 0, totallen);
-               strncpy(st->called_context, ies->called_context, sizeof(st->called_context) - 1);
+               ast_copy_string(st->called_context, ies->called_context, sizeof(st->called_context));
                memcpy(&st->reqeid, ies->reqeid, sizeof(st->reqeid));
                st->trans = trans;
                st->ttl = ies->ttl - 1;
@@ -775,7 +778,8 @@ static int dundi_answer_entity(struct dundi_transaction *trans, struct dundi_ies
                        *st->eids[x-skipfirst] = *ies->eids[x];
                        s += sizeof(dundi_eid);
                }
-               ast_log(LOG_DEBUG, "Answering EID query for '%s@%s'!\n", dundi_eid_to_str(eid_str, sizeof(eid_str), ies->reqeid), ies->called_context);
+               if (option_debug)
+                       ast_log(LOG_DEBUG, "Answering EID query for '%s@%s'!\n", dundi_eid_to_str(eid_str, sizeof(eid_str), ies->reqeid), ies->called_context);
                pthread_attr_init(&attr);
                pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
                trans->thread = 1;
@@ -786,8 +790,10 @@ static int dundi_answer_entity(struct dundi_transaction *trans, struct dundi_ies
                        memset(&ied, 0, sizeof(ied));
                        dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of threads");
                        dundi_send(trans, DUNDI_COMMAND_EIDRESPONSE, 0, 1, &ied);
+                       pthread_attr_destroy(&attr);
                        return -1;
                }
+               pthread_attr_destroy(&attr);
        } else {
                ast_log(LOG_WARNING, "Out of memory!\n");
                memset(&ied, 0, sizeof(ied));
@@ -805,17 +811,17 @@ static int cache_save_hint(dundi_eid *eidpeer, struct dundi_request *req, struct
        char key2[256];
        char eidpeer_str[20];
        char eidroot_str[20];
-       char data[80]="";
+       char data[80];
        time_t timeout;
 
        if (expiration < 0)
-               expiration = DUNDI_DEFAULT_CACHE_TIME;
+               expiration = dundi_cache_time;
 
        /* Only cache hint if "don't ask" is there... */
-       if (!(ntohs(hint->flags)& DUNDI_HINT_DONT_ASK))
+       if (!ast_test_flag_nonstd(hint, htons(DUNDI_HINT_DONT_ASK)))    
                return 0;
 
-       unaffected = ntohs(hint->flags) & DUNDI_HINT_UNAFFECTED;
+       unaffected = ast_test_flag_nonstd(hint, htons(DUNDI_HINT_UNAFFECTED));
 
        dundi_eid_to_str_short(eidpeer_str, sizeof(eidpeer_str), eidpeer);
        dundi_eid_to_str_short(eidroot_str, sizeof(eidroot_str), &req->root_eid);
@@ -827,9 +833,11 @@ static int cache_save_hint(dundi_eid *eidpeer, struct dundi_request *req, struct
        snprintf(data, sizeof(data), "%ld|", (long)(timeout));
        
        ast_db_put("dundi/cache", key1, data);
-       ast_log(LOG_DEBUG, "Caching hint at '%s'\n", key1);
+       if (option_debug)
+               ast_log(LOG_DEBUG, "Caching hint at '%s'\n", key1);
        ast_db_put("dundi/cache", key2, data);
-       ast_log(LOG_DEBUG, "Caching hint at '%s'\n", key2);
+       if (option_debug)
+               ast_log(LOG_DEBUG, "Caching hint at '%s'\n", key2);
        return 0;
 }
 
@@ -838,13 +846,13 @@ static int cache_save(dundi_eid *eidpeer, struct dundi_request *req, int start,
        int x;
        char key1[256];
        char key2[256];
-       char data[1024]="";
+       char data[1024];
        char eidpeer_str[20];
        char eidroot_str[20];
        time_t timeout;
 
        if (expiration < 1)     
-               expiration = DUNDI_DEFAULT_CACHE_TIME;
+               expiration = dundi_cache_time;
 
        /* Keep pushes a little longer, cut pulls a little short */
        if (push)
@@ -900,19 +908,19 @@ static int dundi_prop_precache(struct dundi_transaction *trans, struct dundi_ies
        hmd.flags = DUNDI_HINT_DONT_ASK | DUNDI_HINT_UNAFFECTED;
        dr.dr = dr2;
        dr.maxcount = MAX_RESULTS;
-       dr.expiration = DUNDI_DEFAULT_CACHE_TIME;
+       dr.expiration = dundi_cache_time;
        dr.hmd = &hmd;
        dr.pfds[0] = dr.pfds[1] = -1;
        trans->parent = &dr;
-       strncpy(dr.dcontext, ies->called_context ? ies->called_context : "e164", sizeof(dr.dcontext));
-       strncpy(dr.number, ies->called_number, sizeof(dr.number) - 1);
+       ast_copy_string(dr.dcontext, ies->called_context ? ies->called_context : "e164", sizeof(dr.dcontext));
+       ast_copy_string(dr.number, ies->called_number, sizeof(dr.number));
        
        for (x=0;x<ies->anscount;x++) {
                if (trans->parent->respcount < trans->parent->maxcount) {
                        /* Make sure it's not already there */
                        for (z=0;z<trans->parent->respcount;z++) {
                                if ((trans->parent->dr[z].techint == ies->answers[x]->protocol) &&
-                                   !strcmp(trans->parent->dr[z].dest, ies->answers[x]->data)) 
+                                   !strcmp(trans->parent->dr[z].dest, (char *)ies->answers[x]->data)) 
                                                break;
                        }
                        if (z == trans->parent->respcount) {
@@ -924,16 +932,16 @@ static int dundi_prop_precache(struct dundi_transaction *trans, struct dundi_ies
                                if (ies->expiration > 0)
                                        trans->parent->dr[trans->parent->respcount].expiration = ies->expiration;
                                else
-                                       trans->parent->dr[trans->parent->respcount].expiration = DUNDI_DEFAULT_CACHE_TIME;
+                                       trans->parent->dr[trans->parent->respcount].expiration = dundi_cache_time;
                                dundi_eid_to_str(trans->parent->dr[trans->parent->respcount].eid_str, 
                                        sizeof(trans->parent->dr[trans->parent->respcount].eid_str),
                                        &ies->answers[x]->eid);
-                               strncpy(trans->parent->dr[trans->parent->respcount].dest, ies->answers[x]->data,
+                               ast_copy_string(trans->parent->dr[trans->parent->respcount].dest, (char *)ies->answers[x]->data,
                                        sizeof(trans->parent->dr[trans->parent->respcount].dest));
-                                       strncpy(trans->parent->dr[trans->parent->respcount].tech, tech2str(ies->answers[x]->protocol),
+                                       ast_copy_string(trans->parent->dr[trans->parent->respcount].tech, tech2str(ies->answers[x]->protocol),
                                        sizeof(trans->parent->dr[trans->parent->respcount].tech));
                                trans->parent->respcount++;
-                               trans->parent->hmd->flags &= ~DUNDI_HINT_DONT_ASK;
+                               ast_clear_flag_nonstd(trans->parent->hmd, DUNDI_HINT_DONT_ASK); 
                        } else if (trans->parent->dr[z].weight > ies->answers[x]->weight) {
                                /* Update weight if appropriate */
                                trans->parent->dr[z].weight = ies->answers[x]->weight;
@@ -951,11 +959,9 @@ static int dundi_prop_precache(struct dundi_transaction *trans, struct dundi_ies
        totallen = sizeof(struct dundi_query_state);
        /* Count matching map entries */
        mapcount = 0;
-       cur = mappings;
-       while(cur) {
+       AST_LIST_TRAVERSE(&mappings, cur, list) {
                if (!strcasecmp(cur->dcontext, ccontext))
                        mapcount++;
-               cur = cur->next;
        }
        
        /* If no maps, return -1 immediately */
@@ -974,11 +980,10 @@ static int dundi_prop_precache(struct dundi_transaction *trans, struct dundi_ies
        /* Prepare to run a query and then propagate that as necessary */
        totallen += mapcount * sizeof(struct dundi_mapping);
        totallen += (ies->eidcount - skipfirst) * sizeof(dundi_eid);
-       st = malloc(totallen);
+       st = ast_calloc(1, totallen);
        if (st) {
-               memset(st, 0, totallen);
-               strncpy(st->called_context, ies->called_context, sizeof(st->called_context) - 1);
-               strncpy(st->called_number, ies->called_number, sizeof(st->called_number) - 1);
+               ast_copy_string(st->called_context, ies->called_context, sizeof(st->called_context));
+               ast_copy_string(st->called_number, ies->called_number, sizeof(st->called_number));
                st->trans = trans;
                st->ttl = ies->ttl - 1;
                st->nocache = ies->cbypass;
@@ -994,19 +999,18 @@ static int dundi_prop_precache(struct dundi_transaction *trans, struct dundi_ies
                /* Append mappings */
                x = 0;
                st->maps = (struct dundi_mapping *)s;
-               cur = mappings;
-               while(cur) {
+               AST_LIST_TRAVERSE(&mappings, cur, list) {
                        if (!strcasecmp(cur->dcontext, ccontext)) {
                                if (x < mapcount) {
                                        st->maps[x] = *cur;
-                                       st->maps[x].next = NULL;
+                                       st->maps[x].list.next = NULL;
                                        x++;
                                }
                        }
-                       cur = cur->next;
                }
                st->nummaps = mapcount;
-               ast_log(LOG_DEBUG, "Forwarding precache for '%s@%s'!\n", ies->called_number, ies->called_context);
+               if (option_debug)
+                       ast_log(LOG_DEBUG, "Forwarding precache for '%s@%s'!\n", ies->called_number, ies->called_context);
                pthread_attr_init(&attr);
                pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
                trans->thread = 1;
@@ -1017,8 +1021,10 @@ static int dundi_prop_precache(struct dundi_transaction *trans, struct dundi_ies
                        memset(&ied, 0, sizeof(ied));
                        dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of threads");
                        dundi_send(trans, DUNDI_COMMAND_PRECACHERP, 0, 1, &ied);
+                       pthread_attr_destroy(&attr);
                        return -1;
                }
+               pthread_attr_destroy(&attr);
        } else {
                ast_log(LOG_WARNING, "Out of memory!\n");
                memset(&ied, 0, sizeof(ied));
@@ -1037,19 +1043,16 @@ static int dundi_answer_query(struct dundi_transaction *trans, struct dundi_ies
        struct dundi_ie_data ied;
        char *s;
        struct dundi_mapping *cur;
-       int mapcount;
+       int mapcount = 0;
        int skipfirst = 0;
        
        pthread_t lookupthread;
        pthread_attr_t attr;
        totallen = sizeof(struct dundi_query_state);
        /* Count matching map entries */
-       mapcount = 0;
-       cur = mappings;
-       while(cur) {
+       AST_LIST_TRAVERSE(&mappings, cur, list) {
                if (!strcasecmp(cur->dcontext, ccontext))
                        mapcount++;
-               cur = cur->next;
        }
        /* If no maps, return -1 immediately */
        if (!mapcount)
@@ -1066,11 +1069,10 @@ static int dundi_answer_query(struct dundi_transaction *trans, struct dundi_ies
 
        totallen += mapcount * sizeof(struct dundi_mapping);
        totallen += (ies->eidcount - skipfirst) * sizeof(dundi_eid);
-       st = malloc(totallen);
+       st = ast_calloc(1, totallen);
        if (st) {
-               memset(st, 0, totallen);
-               strncpy(st->called_context, ies->called_context, sizeof(st->called_context) - 1);
-               strncpy(st->called_number, ies->called_number, sizeof(st->called_number) - 1);
+               ast_copy_string(st->called_context, ies->called_context, sizeof(st->called_context));
+               ast_copy_string(st->called_number, ies->called_number, sizeof(st->called_number));
                st->trans = trans;
                st->ttl = ies->ttl - 1;
                st->nocache = ies->cbypass;
@@ -1086,19 +1088,18 @@ static int dundi_answer_query(struct dundi_transaction *trans, struct dundi_ies
                /* Append mappings */
                x = 0;
                st->maps = (struct dundi_mapping *)s;
-               cur = mappings;
-               while(cur) {
+               AST_LIST_TRAVERSE(&mappings, cur, list) {
                        if (!strcasecmp(cur->dcontext, ccontext)) {
                                if (x < mapcount) {
                                        st->maps[x] = *cur;
-                                       st->maps[x].next = NULL;
+                                       st->maps[x].list.next = NULL;
                                        x++;
                                }
                        }
-                       cur = cur->next;
                }
                st->nummaps = mapcount;
-               ast_log(LOG_DEBUG, "Answering query for '%s@%s'!\n", ies->called_number, ies->called_context);
+               if (option_debug)
+                       ast_log(LOG_DEBUG, "Answering query for '%s@%s'!\n", ies->called_number, ies->called_context);
                pthread_attr_init(&attr);
                pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
                trans->thread = 1;
@@ -1109,8 +1110,10 @@ static int dundi_answer_query(struct dundi_transaction *trans, struct dundi_ies
                        memset(&ied, 0, sizeof(ied));
                        dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of threads");
                        dundi_send(trans, DUNDI_COMMAND_DPRESPONSE, 0, 1, &ied);
+                       pthread_attr_destroy(&attr);
                        return -1;
                }
+               pthread_attr_destroy(&attr);
        } else {
                ast_log(LOG_WARNING, "Out of memory!\n");
                memset(&ied, 0, sizeof(ied));
@@ -1123,25 +1126,26 @@ static int dundi_answer_query(struct dundi_transaction *trans, struct dundi_ies
 
 static int cache_lookup_internal(time_t now, struct dundi_request *req, char *key, char *eid_str_full, int *lowexpiration)
 {
-       char data[1024]="";
+       char data[1024];
        char *ptr, *term, *src;
        int tech;
-       int flags;
+       struct ast_flags flags;
        int weight;
        int length;
        int z;
-       int expiration;
        char fs[256];
-       time_t timeout;
+
        /* Build request string */
        if (!ast_db_get("dundi/cache", key, data, sizeof(data))) {
+               time_t timeout;
                ptr = data;
-               if (sscanf(ptr, "%ld|%n", &timeout, &length) == 1) {
-                       expiration = timeout - now;
+               if (!ast_get_time_t(ptr, &timeout, 0, &length)) {
+                       int expiration = timeout - now;
                        if (expiration > 0) {
-                               ast_log(LOG_DEBUG, "Found cache expiring in %d seconds!\n", (int)(timeout - now));
-                               ptr += length;
-                               while((sscanf(ptr, "%d/%d/%d/%n", &flags, &weight, &tech, &length) == 3)) {
+                               if (option_debug)
+                                       ast_log(LOG_DEBUG, "Found cache expiring in %d seconds!\n", expiration);
+                               ptr += length + 1;
+                               while((sscanf(ptr, "%d/%d/%d/%n", &(flags.flags), &weight, &tech, &length) == 3)) {
                                        ptr += length;
                                        term = strchr(ptr, '|');
                                        if (term) {
@@ -1152,8 +1156,9 @@ static int cache_lookup_internal(time_t now, struct dundi_request *req, char *ke
                                                        src++;
                                                } else
                                                        src = "";
-                                               ast_log(LOG_DEBUG, "Found cached answer '%s/%s' originally from '%s' with flags '%s' on behalf of '%s'\n", 
-                                                       tech2str(tech), ptr, src, dundi_flags2str(fs, sizeof(fs), flags), eid_str_full);
+                                               if (option_debug)
+                                                       ast_log(LOG_DEBUG, "Found cached answer '%s/%s' originally from '%s' with flags '%s' on behalf of '%s'\n", 
+                                                               tech2str(tech), ptr, src, dundi_flags2str(fs, sizeof(fs), flags.flags), eid_str_full);
                                                /* Make sure it's not already there */
                                                for (z=0;z<req->respcount;z++) {
                                                        if ((req->dr[z].techint == tech) &&
@@ -1162,19 +1167,19 @@ static int cache_lookup_internal(time_t now, struct dundi_request *req, char *ke
                                                }
                                                if (z == req->respcount) {
                                                        /* Copy into parent responses */
-                                                       req->dr[req->respcount].flags = flags;
+                                                       ast_copy_flags(&(req->dr[req->respcount]), &flags, AST_FLAGS_ALL);      
                                                        req->dr[req->respcount].weight = weight;
                                                        req->dr[req->respcount].techint = tech;
                                                        req->dr[req->respcount].expiration = expiration;
                                                        dundi_str_short_to_eid(&req->dr[req->respcount].eid, src);
                                                        dundi_eid_to_str(req->dr[req->respcount].eid_str, 
                                                                sizeof(req->dr[req->respcount].eid_str), &req->dr[req->respcount].eid);
-                                                       strncpy(req->dr[req->respcount].dest, ptr,
+                                                       ast_copy_string(req->dr[req->respcount].dest, ptr,
                                                                sizeof(req->dr[req->respcount].dest));
-                                                       strncpy(req->dr[req->respcount].tech, tech2str(tech),
+                                                       ast_copy_string(req->dr[req->respcount].tech, tech2str(tech),
                                                                sizeof(req->dr[req->respcount].tech));
                                                        req->respcount++;
-                                                       req->hmd->flags &= ~DUNDI_HINT_DONT_ASK;
+                                                       ast_clear_flag_nonstd(req->hmd, DUNDI_HINT_DONT_ASK);   
                                                } else if (req->dr[z].weight > weight)
                                                        req->dr[z].weight = weight;
                                                ptr = term + 1;
@@ -1233,7 +1238,7 @@ static int cache_lookup(struct dundi_request *req, dundi_eid *peer_eid, unsigned
                        if (res2) {
                                if (strlen(tmp) > strlen(req->hmd->exten)) {
                                        /* Update meta data if appropriate */
-                                       strncpy(req->hmd->exten, tmp, sizeof(req->hmd->exten) - 1);
+                                       ast_copy_string(req->hmd->exten, tmp, sizeof(req->hmd->exten));
                                }
                        }
                }
@@ -1253,7 +1258,7 @@ static void apply_peer(struct dundi_transaction *trans, struct dundi_peer *p)
        trans->them_eid = p->eid;
        /* Enable encryption if appropriate */
        if (!ast_strlen_zero(p->inkey))
-               trans->flags |= FLAG_ENCRYPT;
+               ast_set_flag(trans, FLAG_ENCRYPT);      
        if (p->maxms) {
                trans->autokilltimeout = p->maxms;
                trans->retranstimer = DUNDI_DEFAULT_RETRANS_TIMER;
@@ -1269,12 +1274,13 @@ static void apply_peer(struct dundi_transaction *trans, struct dundi_peer *p)
                trans->autokilltimeout = global_autokilltimeout;
 }
 
+/*! \note Called with the peers list already locked */
 static int do_register_expire(void *data)
 {
        struct dundi_peer *peer = data;
        char eid_str[20];
-       /* Called with peerlock already held */
-       ast_log(LOG_DEBUG, "Register expired for '%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
+       if (option_debug)
+               ast_log(LOG_DEBUG, "Register expired for '%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
        peer->registerexpire = -1;
        peer->lastms = 0;
        memset(&peer->addr, 0, sizeof(peer->addr));
@@ -1307,7 +1313,7 @@ static int update_key(struct dundi_peer *peer)
                        ast_log(LOG_NOTICE, "Whoa, got a weird encrypt size (%d != %d)!\n", res, 128);
                        return -1;
                }
-               if ((res = ast_sign_bin(skey, peer->txenckey, 128, peer->txenckey + 128))) {
+               if ((res = ast_sign_bin(skey, (char *)peer->txenckey, 128, peer->txenckey + 128))) {
                        ast_log(LOG_NOTICE, "Failed to sign key (%d)!\n", res);
                        return -1;
                }
@@ -1368,7 +1374,8 @@ static struct dundi_hdr *dundi_decrypt(struct dundi_transaction *trans, unsigned
        *h = *ohdr;
        bytes = space - 6;
        if (uncompress(dst + 6, &bytes, decrypt_space, srclen) != Z_OK) {
-               ast_log(LOG_DEBUG, "Ouch, uncompress failed :(\n");
+               if (option_debug)
+                       ast_log(LOG_DEBUG, "Ouch, uncompress failed :(\n");
                return NULL;
        }
        /* Update length */
@@ -1394,7 +1401,8 @@ static int dundi_encrypt(struct dundi_transaction *trans, struct dundi_packet *p
                bytes = len;
                res = compress(compress_space, &bytes, pack->data + 6, pack->datalen - 6);
                if (res != Z_OK) {
-                       ast_log(LOG_DEBUG, "Ouch, compression failed!\n");
+                       if (option_debug)
+                               ast_log(LOG_DEBUG, "Ouch, compression failed!\n");
                        return -1;
                }
                memset(&ied, 0, sizeof(ied));
@@ -1406,10 +1414,10 @@ static int dundi_encrypt(struct dundi_transaction *trans, struct dundi_packet *p
                        if (update_key(peer))
                                return -1;
                        if (!peer->sentfullkey)
-                               trans->flags |= FLAG_SENDFULLKEY;
+                               ast_set_flag(trans, FLAG_SENDFULLKEY);  
                        /* Append key data */
                        dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid);
-                       if (trans->flags & FLAG_SENDFULLKEY) {
+                       if (ast_test_flag(trans, FLAG_SENDFULLKEY)) {
                                dundi_ie_append_raw(&ied, DUNDI_IE_SHAREDKEY, peer->txenckey, 128);
                                dundi_ie_append_raw(&ied, DUNDI_IE_SIGNATURE, peer->txenckey + 128, 128);
                        } else {
@@ -1478,7 +1486,7 @@ static int check_key(struct dundi_peer *peer, unsigned char *newkey, unsigned ch
        }
 
        /* First check signature */
-       res = ast_check_signature_bin(skey, newkey, 128, newsig);
+       res = ast_check_signature_bin(skey, (char *)newkey, 128, newsig);
        if (res) 
                return 0;
 
@@ -1489,7 +1497,8 @@ static int check_key(struct dundi_peer *peer, unsigned char *newkey, unsigned ch
                return 0;
        }
        /* Decrypted, passes signature */
-       ast_log(LOG_DEBUG, "Wow, new key combo passed signature and decrypt!\n");
+       if (option_debug)
+               ast_log(LOG_DEBUG, "Wow, new key combo passed signature and decrypt!\n");
        memcpy(peer->rxenckey, newkey, 128);
        memcpy(peer->rxenckey + 128, newsig, 128);
        peer->them_keycrc32 = crc32(0L, peer->rxenckey, 128);
@@ -1521,7 +1530,8 @@ static int handle_command_response(struct dundi_transaction *trans, struct dundi
                        return -1;
                /* Make a copy for parsing */
                memcpy(bufcpy, hdr->ies, datalen);
-               ast_log(LOG_DEBUG, "Got canonical message %d (%d), %d bytes data%s\n", cmd, hdr->oseqno, datalen, final ? " (Final)" : "");
+               if (option_debug)
+                       ast_log(LOG_DEBUG, "Got canonical message %d (%d), %d bytes data%s\n", cmd, hdr->oseqno, datalen, final ? " (Final)" : "");
                if (dundi_parse_ies(&ies, bufcpy, datalen) < 0) {
                        ast_log(LOG_WARNING, "Failed to parse DUNDI information elements!\n");
                        return -1;
@@ -1556,13 +1566,13 @@ static int handle_command_response(struct dundi_transaction *trans, struct dundi
                                if (cmd == DUNDI_COMMAND_EIDQUERY) {
                                        res = dundi_answer_entity(trans, &ies, ies.called_context);
                                } else {
-                                       if (!ies.called_number || ast_strlen_zero(ies.called_number)) {
+                                       if (ast_strlen_zero(ies.called_number)) {
                                                /* They're not permitted to access that context */
                                                dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Invalid or missing number/entity");
                                                dundi_send(trans, resp, 0, 1, &ied);
                                        } else if ((cmd == DUNDI_COMMAND_DPDISCOVER) && 
                                                   (peer->model & DUNDI_MODEL_INBOUND) && 
-                                                          has_permission(peer->permit, ies.called_context)) {
+                                                          has_permission(&peer->permit, ies.called_context)) {
                                                res = dundi_answer_query(trans, &ies, ies.called_context);
                                                if (res < 0) {
                                                        /* There is no such dundi context */
@@ -1571,7 +1581,7 @@ static int handle_command_response(struct dundi_transaction *trans, struct dundi
                                                }
                                        } else if ((cmd = DUNDI_COMMAND_PRECACHERQ) && 
                                                   (peer->pcmodel & DUNDI_MODEL_INBOUND) && 
-                                                          has_permission(peer->include, ies.called_context)) {
+                                                          has_permission(&peer->include, ies.called_context)) {
                                                res = dundi_prop_precache(trans, &ies, ies.called_context);
                                                if (res < 0) {
                                                        /* There is no such dundi context */
@@ -1606,18 +1616,20 @@ static int handle_command_response(struct dundi_transaction *trans, struct dundi
                                hasauth = 1;
                        if (hasauth) {
                                int expire = default_expiration;
-                               char iabuf[INET_ADDRSTRLEN];
                                char data[256];
                                int needqual = 0;
                                if (peer->registerexpire > -1)
                                        ast_sched_del(sched, peer->registerexpire);
                                peer->registerexpire = ast_sched_add(sched, (expire + 10) * 1000, do_register_expire, peer);
-                               ast_inet_ntoa(iabuf, sizeof(iabuf), trans->addr.sin_addr);
-                               snprintf(data, sizeof(data), "%s:%d:%d", iabuf, ntohs(trans->addr.sin_port), expire);
+                               snprintf(data, sizeof(data), "%s:%d:%d", ast_inet_ntoa(trans->addr.sin_addr), 
+                                       ntohs(trans->addr.sin_port), expire);
                                ast_db_put("dundi/dpeers", dundi_eid_to_str_short(eid_str, sizeof(eid_str), &peer->eid), data);
                                if (inaddrcmp(&peer->addr, &trans->addr)) {
-                                       if (option_verbose > 2)
-                                               ast_verbose(VERBOSE_PREFIX_3 "Registered DUNDi peer '%s' at '%s:%d'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), iabuf, ntohs(trans->addr.sin_port));
+                                       if (option_verbose > 2) {
+                                               ast_verbose(VERBOSE_PREFIX_3 "Registered DUNDi peer '%s' at '%s:%d'\n", 
+                                                       dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), 
+                                                       ast_inet_ntoa(trans->addr.sin_addr), ntohs(trans->addr.sin_port));
+                                       }
                                        needqual = 1;
                                }
                                        
@@ -1633,8 +1645,9 @@ static int handle_command_response(struct dundi_transaction *trans, struct dundi
                /* A dialplan response, lets see what we got... */
                if (ies.cause < 1) {
                        /* Success of some sort */
-                       ast_log(LOG_DEBUG, "Looks like success of some sort (%d), %d answers\n", ies.cause, ies.anscount);
-                       if (trans->flags & FLAG_ENCRYPT) {
+                       if (option_debug)
+                               ast_log(LOG_DEBUG, "Looks like success of some sort (%d), %d answers\n", ies.cause, ies.anscount);
+                       if (ast_test_flag(trans, FLAG_ENCRYPT)) {
                                authpass = encrypted;
                        } else 
                                authpass = 1;
@@ -1647,7 +1660,7 @@ static int handle_command_response(struct dundi_transaction *trans, struct dundi
                                                        /* Make sure it's not already there */
                                                        for (z=0;z<trans->parent->respcount;z++) {
                                                                if ((trans->parent->dr[z].techint == ies.answers[x]->protocol) &&
-                                                                   !strcmp(trans->parent->dr[z].dest, ies.answers[x]->data)) 
+                                                                   !strcmp(trans->parent->dr[z].dest, (char *)ies.answers[x]->data)) 
                                                                                break;
                                                        }
                                                        if (z == trans->parent->respcount) {
@@ -1659,16 +1672,16 @@ static int handle_command_response(struct dundi_transaction *trans, struct dundi
                                                                if (ies.expiration > 0)
                                                                        trans->parent->dr[trans->parent->respcount].expiration = ies.expiration;
                                                                else
-                                                                       trans->parent->dr[trans->parent->respcount].expiration = DUNDI_DEFAULT_CACHE_TIME;
+                                                                       trans->parent->dr[trans->parent->respcount].expiration = dundi_cache_time;
                                                                dundi_eid_to_str(trans->parent->dr[trans->parent->respcount].eid_str, 
                                                                        sizeof(trans->parent->dr[trans->parent->respcount].eid_str),
                                                                        &ies.answers[x]->eid);
-                                                               strncpy(trans->parent->dr[trans->parent->respcount].dest, ies.answers[x]->data,
+                                                               ast_copy_string(trans->parent->dr[trans->parent->respcount].dest, (char *)ies.answers[x]->data,
                                                                        sizeof(trans->parent->dr[trans->parent->respcount].dest));
-                                                               strncpy(trans->parent->dr[trans->parent->respcount].tech, tech2str(ies.answers[x]->protocol),
+                                                               ast_copy_string(trans->parent->dr[trans->parent->respcount].tech, tech2str(ies.answers[x]->protocol),
                                                                        sizeof(trans->parent->dr[trans->parent->respcount].tech));
                                                                trans->parent->respcount++;
-                                                               trans->parent->hmd->flags &= ~DUNDI_HINT_DONT_ASK;
+                                                               ast_clear_flag_nonstd(trans->parent->hmd, DUNDI_HINT_DONT_ASK);
                                                        } else if (trans->parent->dr[z].weight > ies.answers[x]->weight) {
                                                                /* Update weight if appropriate */
                                                                trans->parent->dr[z].weight = ies.answers[x]->weight;
@@ -1680,18 +1693,18 @@ static int handle_command_response(struct dundi_transaction *trans, struct dundi
                                        /* Save all the results (if any) we had.  Even if no results, still cache lookup.  Let
                                           the cache know if this request was unaffected by our entity list. */
                                        cache_save(&trans->them_eid, trans->parent, y, 
-                                                       ies.hint ? ntohs(ies.hint->flags) & DUNDI_HINT_UNAFFECTED : 0, ies.expiration, 0);
+                                                       ies.hint ? ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_UNAFFECTED)) : 0, ies.expiration, 0);
                                        if (ies.hint) {
                                                cache_save_hint(&trans->them_eid, trans->parent, ies.hint, ies.expiration);
-                                               if (ntohs(ies.hint->flags) & DUNDI_HINT_TTL_EXPIRED)
-                                                       trans->parent->hmd->flags |= DUNDI_HINT_TTL_EXPIRED;
-                                               if (ntohs(ies.hint->flags) & DUNDI_HINT_DONT_ASK) { 
-                                                       if (strlen(ies.hint->data) > strlen(trans->parent->hmd->exten)) {
-                                                               strncpy(trans->parent->hmd->exten, ies.hint->data, 
-                                                                       sizeof(trans->parent->hmd->exten) - 1);
+                                               if (ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_TTL_EXPIRED)))
+                                                       ast_set_flag_nonstd(trans->parent->hmd, DUNDI_HINT_TTL_EXPIRED);
+                                               if (ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_DONT_ASK))) { 
+                                                       if (strlen((char *)ies.hint->data) > strlen(trans->parent->hmd->exten)) {
+                                                               ast_copy_string(trans->parent->hmd->exten, (char *)ies.hint->data, 
+                                                                       sizeof(trans->parent->hmd->exten));
                                                        }
                                                } else {
-                                                       trans->parent->hmd->flags &= ~DUNDI_HINT_DONT_ASK;
+                                                       ast_clear_flag_nonstd(trans->parent->hmd, DUNDI_HINT_DONT_ASK);
                                                }
                                        }
                                        if (ies.expiration > 0) {
@@ -1717,8 +1730,9 @@ static int handle_command_response(struct dundi_transaction *trans, struct dundi
                /* A dialplan response, lets see what we got... */
                if (ies.cause < 1) {
                        /* Success of some sort */
-                       ast_log(LOG_DEBUG, "Looks like success of some sort (%d)\n", ies.cause);
-                       if (trans->flags & FLAG_ENCRYPT) {
+                       if (option_debug)
+                               ast_log(LOG_DEBUG, "Looks like success of some sort (%d)\n", ies.cause);
+                       if (ast_test_flag(trans, FLAG_ENCRYPT)) {
                                authpass = encrypted;
                        } else 
                                authpass = 1;
@@ -1728,30 +1742,29 @@ static int handle_command_response(struct dundi_transaction *trans, struct dundi
                                        if (!trans->parent->respcount) {
                                                trans->parent->respcount++;
                                                if (ies.q_dept)
-                                                       strncpy(trans->parent->dei->orgunit, ies.q_dept, sizeof(trans->parent->dei->orgunit) - 1);
+                                                       ast_copy_string(trans->parent->dei->orgunit, ies.q_dept, sizeof(trans->parent->dei->orgunit));
                                                if (ies.q_org)
-                                                       strncpy(trans->parent->dei->org, ies.q_org, sizeof(trans->parent->dei->org) - 1);
+                                                       ast_copy_string(trans->parent->dei->org, ies.q_org, sizeof(trans->parent->dei->org));
                                                if (ies.q_locality)
-                                                       strncpy(trans->parent->dei->locality, ies.q_locality, sizeof(trans->parent->dei->locality) - 1);
+                                                       ast_copy_string(trans->parent->dei->locality, ies.q_locality, sizeof(trans->parent->dei->locality));
                                                if (ies.q_stateprov)
-                                                       strncpy(trans->parent->dei->stateprov, ies.q_stateprov, sizeof(trans->parent->dei->stateprov) - 1);
+                                                       ast_copy_string(trans->parent->dei->stateprov, ies.q_stateprov, sizeof(trans->parent->dei->stateprov));
                                                if (ies.q_country)
-                                                       strncpy(trans->parent->dei->country, ies.q_country, sizeof(trans->parent->dei->country) - 1);
+                                                       ast_copy_string(trans->parent->dei->country, ies.q_country, sizeof(trans->parent->dei->country));
                                                if (ies.q_email)
-                                                       strncpy(trans->parent->dei->email, ies.q_email, sizeof(trans->parent->dei->email) - 1);
+                                                       ast_copy_string(trans->parent->dei->email, ies.q_email, sizeof(trans->parent->dei->email));
                                                if (ies.q_phone)
-                                                       strncpy(trans->parent->dei->phone, ies.q_phone, sizeof(trans->parent->dei->phone) - 1);
+                                                       ast_copy_string(trans->parent->dei->phone, ies.q_phone, sizeof(trans->parent->dei->phone));
                                                if (ies.q_ipaddr)
-                                                       strncpy(trans->parent->dei->ipaddr, ies.q_ipaddr, sizeof(trans->parent->dei->ipaddr) - 1);
+                                                       ast_copy_string(trans->parent->dei->ipaddr, ies.q_ipaddr, sizeof(trans->parent->dei->ipaddr));
                                                if (!dundi_eid_cmp(&trans->them_eid, &trans->parent->query_eid)) {
                                                        /* If it's them, update our address */
-                                                       ast_inet_ntoa(trans->parent->dei->ipaddr, sizeof(trans->parent->dei->ipaddr),
-                                                               trans->addr.sin_addr);
+                                                       ast_copy_string(trans->parent->dei->ipaddr, ast_inet_ntoa(trans->addr.sin_addr), sizeof(trans->parent->dei->ipaddr));
                                                }
                                        }
                                        if (ies.hint) {
-                                               if (ntohs(ies.hint->flags) & DUNDI_HINT_TTL_EXPIRED)
-                                                       trans->parent->hmd->flags |= DUNDI_HINT_TTL_EXPIRED;
+                                               if (ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_TTL_EXPIRED)))
+                                                       ast_set_flag_nonstd(trans->parent->hmd, DUNDI_HINT_TTL_EXPIRED);
                                        }
                                }
                                /* Close connection if not final */
@@ -1772,7 +1785,7 @@ static int handle_command_response(struct dundi_transaction *trans, struct dundi
                if (ies.cause < 1) {
                        int hasauth;
                        /* Success of some sort */
-                       if (trans->flags & FLAG_ENCRYPT) {
+                       if (ast_test_flag(trans, FLAG_ENCRYPT)) {
                                hasauth = encrypted;
                        } else 
                                hasauth = 1;
@@ -1784,8 +1797,9 @@ static int handle_command_response(struct dundi_transaction *trans, struct dundi
                                        dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, &ied);
                                }
                        } else {
-                               ast_log(LOG_DEBUG, "Yay, we've registered as '%s' to '%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &trans->us_eid),
-                                                       dundi_eid_to_str(eid_str2, sizeof(eid_str2), &trans->them_eid));
+                               if (option_debug)
+                                       ast_log(LOG_DEBUG, "Yay, we've registered as '%s' to '%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &trans->us_eid),
+                                                               dundi_eid_to_str(eid_str2, sizeof(eid_str2), &trans->them_eid));
                                /* Close connection if not final */
                                if (!final) 
                                        dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
@@ -1805,13 +1819,13 @@ static int handle_command_response(struct dundi_transaction *trans, struct dundi
                        dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
                break;
        case DUNDI_COMMAND_ENCREJ:
-               if ((trans->flags & FLAG_SENDFULLKEY) || !trans->lasttrans || !(peer = find_peer(&trans->them_eid))) {
+               if ((ast_test_flag(trans, FLAG_SENDFULLKEY)) || AST_LIST_EMPTY(&trans->lasttrans) || !(peer = find_peer(&trans->them_eid))) {
                        /* No really, it's over at this point */
                        if (!final) 
                                dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
                } else {
                        /* Send with full key */
-                       trans->flags |= FLAG_SENDFULLKEY;
+                       ast_set_flag(trans, FLAG_SENDFULLKEY);
                        if (final) {
                                /* Ooops, we got a final message, start by sending ACK... */
                                dundi_ack(trans, hdr->cmdresp & 0x80);
@@ -1822,7 +1836,7 @@ static int handle_command_response(struct dundi_transaction *trans, struct dundi
                                        hdr->cmdresp &= 0x7f;
                                        /* Parse the message we transmitted */
                                        memset(&ies, 0, sizeof(ies));
-                                       dundi_parse_ies(&ies, trans->lasttrans->h->ies, trans->lasttrans->datalen - sizeof(struct dundi_hdr));
+                                       dundi_parse_ies(&ies, (AST_LIST_FIRST(&trans->lasttrans))->h->ies, (AST_LIST_FIRST(&trans->lasttrans))->datalen - sizeof(struct dundi_hdr));
                                        /* Reconstruct outgoing encrypted packet */
                                        memset(&ied, 0, sizeof(ied));
                                        dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid);
@@ -1830,7 +1844,7 @@ static int handle_command_response(struct dundi_transaction *trans, struct dundi
                                        dundi_ie_append_raw(&ied, DUNDI_IE_SIGNATURE, peer->txenckey + 128, 128);
                                        if (ies.encblock) 
                                                dundi_ie_append_encdata(&ied, DUNDI_IE_ENCDATA, ies.encblock->iv, ies.encblock->encdata, ies.enclen);
-                                       dundi_send(trans, DUNDI_COMMAND_ENCRYPT, 0, trans->lasttrans->h->cmdresp & 0x80, &ied);
+                                       dundi_send(trans, DUNDI_COMMAND_ENCRYPT, 0, (AST_LIST_FIRST(&trans->lasttrans))->h->cmdresp & 0x80, &ied);
                                        peer->sentfullkey = 1;
                                }
                        }
@@ -1853,7 +1867,7 @@ static int handle_command_response(struct dundi_transaction *trans, struct dundi
                                trans->ecx = peer->them_ecx;
                                trans->dcx = peer->them_dcx;
                        }
-                       if ((trans->flags & FLAG_ENCRYPT) && ies.encblock && ies.enclen) {
+                       if (ast_test_flag(trans, FLAG_ENCRYPT) && ies.encblock && ies.enclen) {
                                struct dundi_hdr *dhdr;
                                unsigned char decoded[MAX_PACKET_SIZE];
                                int ddatalen;
@@ -1867,13 +1881,15 @@ static int handle_command_response(struct dundi_transaction *trans, struct dundi
                                        /* Carry back final flag */
                                        hdr->cmdresp |= dhdr->cmdresp & 0x80;
                                        break;
-                               } else
-                                       ast_log(LOG_DEBUG, "Ouch, decrypt failed :(\n");
+                               } else {
+                                       if (option_debug)
+                                               ast_log(LOG_DEBUG, "Ouch, decrypt failed :(\n");
+                               }
                        }
                }
                if (!final) {
                        /* Turn off encryption */
-                       trans->flags &= ~FLAG_ENCRYPT;
+                       ast_clear_flag(trans, FLAG_ENCRYPT);
                        dundi_send(trans, DUNDI_COMMAND_ENCREJ, 0, 1, NULL);
                }
                break;
@@ -1889,39 +1905,38 @@ static int handle_command_response(struct dundi_transaction *trans, struct dundi
 }
 
 static void destroy_packet(struct dundi_packet *pack, int needfree);
-static void destroy_packets(struct dundi_packet *p)
+static void destroy_packets(struct packetlist *p)
 {
-       struct dundi_packet *prev;
-       while(p) {
-               prev = p;
-               p = p->next;
-               if (prev->retransid > -1)
-                       ast_sched_del(sched, prev->retransid);
-               free(prev);
+       struct dundi_packet *pack;
+       
+       while ((pack = AST_LIST_REMOVE_HEAD(p, list))) {
+               if (pack->retransid > -1)
+                       ast_sched_del(sched, pack->retransid);
+               free(pack);
        }
 }
 
 
 static int ack_trans(struct dundi_transaction *trans, int iseqno)
 {
-       /* Ack transmitted packet corresponding to iseqno */
        struct dundi_packet *pack;
-       pack = trans->packets;
-       while(pack) {
+
+       /* Ack transmitted packet corresponding to iseqno */
+       AST_LIST_TRAVERSE(&trans->packets, pack, list) {
                if ((pack->h->oseqno + 1) % 255 == iseqno) {
                        destroy_packet(pack, 0);
-                       if (trans->lasttrans) {
+                       if (!AST_LIST_EMPTY(&trans->lasttrans)) {
                                ast_log(LOG_WARNING, "Whoa, there was still a last trans?\n");
-                               destroy_packets(trans->lasttrans);
+                               destroy_packets(&trans->lasttrans);
                        }
-                       trans->lasttrans = pack;
+                       AST_LIST_INSERT_HEAD(&trans->lasttrans, pack, list);
                        if (trans->autokillid > -1)
                                ast_sched_del(sched, trans->autokillid);
                        trans->autokillid = -1;
                        return 1;
                }
-               pack = pack->next;
        }
+
        return 0;
 }
 
@@ -1936,7 +1951,7 @@ static int handle_frame(struct dundi_hdr *h, struct sockaddr_in *sin, int datale
        /* Got a transaction, see where this header fits in */
        if (h->oseqno == trans->iseqno) {
                /* Just what we were looking for...  Anything but ack increments iseqno */
-               if (ack_trans(trans, h->iseqno) && (trans->flags & FLAG_FINAL)) {
+               if (ack_trans(trans, h->iseqno) && ast_test_flag(trans, FLAG_FINAL)) {
                        /* If final, we're done */
                        destroy_trans(trans, 0);
                        return 0;
@@ -1951,8 +1966,7 @@ static int handle_frame(struct dundi_hdr *h, struct sockaddr_in *sin, int datale
                        trans->aseqno = trans->iseqno;
                }
                /* Delete any saved last transmissions */
-               destroy_packets(trans->lasttrans);
-               trans->lasttrans = NULL;
+               destroy_packets(&trans->lasttrans);
                if (h->cmdresp & 0x80) {
                        /* Final -- destroy now */
                        destroy_trans(trans, 0);
@@ -1962,7 +1976,8 @@ static int handle_frame(struct dundi_hdr *h, struct sockaddr_in *sin, int datale
                dundi_ack(trans, 0);
        } else {
                /* Out of window -- simply drop */
-               ast_log(LOG_DEBUG, "Dropping packet out of window!\n");
+               if (option_debug)
+                       ast_log(LOG_DEBUG, "Dropping packet out of window!\n");
        }
        return 0;
 }
@@ -1972,9 +1987,9 @@ static int socket_read(int *id, int fd, short events, void *cbdata)
        struct sockaddr_in sin;
        int res;
        struct dundi_hdr *h;
-       unsigned char buf[MAX_PACKET_SIZE];
-       int len;
-       len = sizeof(sin);
+       char buf[MAX_PACKET_SIZE];
+       socklen_t len = sizeof(sin);
+       
        res = recvfrom(netsocket, buf, sizeof(buf) - 1, 0,(struct sockaddr *) &sin, &len);
        if (res < 0) {
                if (errno != ECONNREFUSED)
@@ -1986,22 +2001,22 @@ static int socket_read(int *id, int fd, short events, void *cbdata)
                return 1;
        }
        buf[res] = '\0';
-       h = (struct dundi_hdr *)buf;
+       h = (struct dundi_hdr *) buf;
        if (dundidebug)
                dundi_showframe(h, 1, &sin, res - sizeof(struct dundi_hdr));
-       ast_mutex_lock(&peerlock);
+       AST_LIST_LOCK(&peers);
        handle_frame(h, &sin, res - sizeof(struct dundi_hdr));
-       ast_mutex_unlock(&peerlock);
+       AST_LIST_UNLOCK(&peers);
        return 1;
 }
 
 static void build_secret(char *secret, int seclen)
 {
-       char tmp[16];
+       unsigned char tmp[16];
        char *s;
        build_iv(tmp);
        secret[0] = '\0';
-       ast_base64encode(secret ,tmp, sizeof(tmp), seclen);
+       ast_base64encode(secret, tmp, sizeof(tmp), seclen);
        /* Eliminate potential bad characters */
        while((s = strchr(secret, ';'))) *s = '+';
        while((s = strchr(secret, '/'))) *s = '+';
@@ -2019,7 +2034,7 @@ static void save_secret(const char *newkey, const char *oldkey)
                snprintf(tmp, sizeof(tmp), "%s", newkey);
        rotatetime = time(NULL) + DUNDI_SECRET_TIME;
        ast_db_put(secretpath, "secret", tmp);
-       snprintf(tmp, sizeof(tmp), "%ld", rotatetime);
+       snprintf(tmp, sizeof(tmp), "%d", (int)rotatetime);
        ast_db_put(secretpath, "secretexpiry", tmp);
 }
 
@@ -2031,7 +2046,7 @@ static void load_password(void)
        time_t expired;
        
        ast_db_get(secretpath, "secretexpiry", tmp, sizeof(tmp));
-       if (sscanf(tmp, "%ld", &expired) == 1) {
+       if (!ast_get_time_t(tmp, &expired, 0, NULL)) {
                ast_db_get(secretpath, "secret", tmp, sizeof(tmp));
                current = strchr(tmp, ';');
                if (!current)
@@ -2053,7 +2068,7 @@ static void load_password(void)
        }
        if (current) {
                /* Current key is still valid, just setup rotatation properly */
-               strncpy(cursecret, current, sizeof(cursecret) - 1);
+               ast_copy_string(cursecret, current, sizeof(cursecret));
                rotatetime = expired;
        } else {
                /* Current key is out of date, rotate or eliminate all together */
@@ -2073,7 +2088,7 @@ static void check_password(void)
 #endif
        if ((now - rotatetime) >= 0) {
                /* Time to rotate keys */
-               strncpy(oldsecret, cursecret, sizeof(oldsecret) - 1);
+               ast_copy_string(oldsecret, cursecret, sizeof(oldsecret));
                build_secret(cursecret, sizeof(cursecret));
                save_secret(cursecret, oldsecret);
        }
@@ -2092,9 +2107,9 @@ static void *network_thread(void *ignore)
                        res = 1000;
                res = ast_io_wait(io, res);
                if (res >= 0) {
-                       ast_mutex_lock(&peerlock);
+                       AST_LIST_LOCK(&peers);
                        ast_sched_runq(sched);
-                       ast_mutex_unlock(&peerlock);
+                       AST_LIST_UNLOCK(&peers);
                }
                check_password();
        }
@@ -2105,40 +2120,41 @@ static void *process_precache(void *ign)
 {
        struct dundi_precache_queue *qe;
        time_t now;
-       char context[256]="";
-       char number[256]="";
+       char context[256];
+       char number[256];
        int run;
+
        for (;;) {
                time(&now);
                run = 0;
-               ast_mutex_lock(&pclock);
-               if (pcq) {
-                       if (!pcq->expiration) {
+               AST_LIST_LOCK(&pcq);
+               if ((qe = AST_LIST_FIRST(&pcq))) {
+                       if (!qe->expiration) {
                                /* Gone...  Remove... */
-                               qe = pcq;
-                               pcq = pcq->next;
+                               AST_LIST_REMOVE_HEAD(&pcq, list);
                                free(qe);
-                       } else if (pcq->expiration < now) {
+                       } else if (qe->expiration < now) {
                                /* Process this entry */
-                               pcq->expiration = 0;
-                               strncpy(context, pcq->context, sizeof(context) - 1);
-                               strncpy(number, pcq->number, sizeof(number) - 1);
+                               qe->expiration = 0;
+                               ast_copy_string(context, qe->context, sizeof(context));
+                               ast_copy_string(number, qe->number, sizeof(number));
                                run = 1;
                        }
                }
-               ast_mutex_unlock(&pclock);
+               AST_LIST_UNLOCK(&pcq);
                if (run) {
                        dundi_precache(context, number);
                } else
                        sleep(1);
        }
+
        return NULL;
 }
 
 static int start_network_thread(void)
 {
-       ast_pthread_create(&netthreadid, NULL, network_thread, NULL);
-       ast_pthread_create(&precachethreadid, NULL, process_precache, NULL);
+       ast_pthread_create_background(&netthreadid, NULL, network_thread, NULL);
+       ast_pthread_create_background(&precachethreadid, NULL, process_precache, NULL);
        return 0;
 }
 
@@ -2162,7 +2178,7 @@ static int dundi_do_store_history(int fd, int argc, char *argv[])
 
 static int dundi_flush(int fd, int argc, char *argv[])
 {
-       int stats=0;
+       int stats = 0;
        if ((argc < 2) || (argc > 3))
                return RESULT_SHOWUSAGE;
        if (argc > 2) {
@@ -2175,19 +2191,17 @@ static int dundi_flush(int fd, int argc, char *argv[])
                /* Flush statistics */
                struct dundi_peer *p;
                int x;
-               ast_mutex_lock(&peerlock);
-               p = peers;
-               while(p) {
-                       for (x=0;x<DUNDI_TIMING_HISTORY;x++) {
+               AST_LIST_LOCK(&peers);
+               AST_LIST_TRAVERSE(&peers, p, list) {
+                       for (x = 0;x < DUNDI_TIMING_HISTORY; x++) {
                                if (p->lookups[x])
                                        free(p->lookups[x]);
                                p->lookups[x] = NULL;
                                p->lookuptimes[x] = 0;
                        }
                        p->avgms = 0;
-                       p = p->next;
                }
-               ast_mutex_unlock(&peerlock);
+               AST_LIST_UNLOCK(&peers);
        } else {
                ast_db_deltree("dundi/cache", NULL);
                ast_cli(fd, "DUNDi Cache Flushed\n");
@@ -2227,32 +2241,27 @@ static char *model2str(int model)
        }
 }
 
-static char *complete_peer_helper(char *line, char *word, int pos, int state, int rpos)
+static char *complete_peer_helper(const char *line, const char *word, int pos, int state, int rpos)
 {
-       int which=0;
-       char *ret;
+       int which=0, len;
+       char *ret = NULL;
        struct dundi_peer *p;
        char eid_str[20];
+
        if (pos != rpos)
                return NULL;
-       ast_mutex_lock(&peerlock);
-       p = peers;
-       while(p) {
-               if (!strncasecmp(word, dundi_eid_to_str(eid_str, sizeof(eid_str), &p->eid), strlen(word))) {
-                       if (++which > state)
-                               break;
-               }
-               p = p->next;
-       }
-       if (p) {
-               ret = strdup(dundi_eid_to_str(eid_str, sizeof(eid_str), &p->eid));
-       } else
-               ret = NULL;
-       ast_mutex_unlock(&peerlock);
+       AST_LIST_LOCK(&peers);
+       len = strlen(word);
+       AST_LIST_TRAVERSE(&peers, p, list) {
+               const char *s = dundi_eid_to_str(eid_str, sizeof(eid_str), &p->eid);
+               if (!strncasecmp(word, s, len) && ++which > state)
+                       ret = ast_strdup(s);
+       }
+       AST_LIST_UNLOCK(&peers);
        return ret;
 }
 
-static char *complete_peer_4(char *line, char *word, int pos, int state)
+static char *complete_peer_4(const char *line, const char *word, int pos, int state)
 {
        return complete_peer_helper(line, word, pos, state, 3);
 }
@@ -2277,7 +2286,7 @@ static void sort_results(struct dundi_result *results, int count)
 static int dundi_do_lookup(int fd, int argc, char *argv[])
 {
        int res;
-       char tmp[256] = "";
+       char tmp[256];
        char fs[80] = "";
        char *context;
        int x;
@@ -2292,13 +2301,13 @@ static int dundi_do_lookup(int fd, int argc, char *argv[])
                else
                        return RESULT_SHOWUSAGE;
        }
-       strncpy(tmp, argv[2], sizeof(tmp) - 1);
+       ast_copy_string(tmp, argv[2], sizeof(tmp));
        context = strchr(tmp, '@');
        if (context) {
                *context = '\0';
                context++;
        }
-       gettimeofday(&start, NULL);
+       start = ast_tvnow();
        res = dundi_lookup(dr, MAX_RESULTS, NULL, context, tmp, bypass);
        
        if (res < 0) 
@@ -2311,39 +2320,39 @@ static int dundi_do_lookup(int fd, int argc, char *argv[])
                ast_cli(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));
                ast_cli(fd, "     from %s, expires in %d s\n", dr[x].eid_str, dr[x].expiration);
        }
-       ast_cli(fd, "DUNDi lookup completed in %d ms\n", calc_ms(&start));
+       ast_cli(fd, "DUNDi lookup completed in %d ms\n", ast_tvdiff_ms(ast_tvnow(), start));
        return RESULT_SUCCESS;
 }
 
 static int dundi_do_precache(int fd, int argc, char *argv[])
 {
        int res;
-       char tmp[256] = "";
+       char tmp[256];
        char *context;
        struct timeval start;
        if ((argc < 3) || (argc > 3))
                return RESULT_SHOWUSAGE;
-       strncpy(tmp, argv[2], sizeof(tmp) - 1);
+       ast_copy_string(tmp, argv[2], sizeof(tmp));
        context = strchr(tmp, '@');
        if (context) {
                *context = '\0';
                context++;
        }
-       gettimeofday(&start, NULL);
+       start = ast_tvnow();
        res = dundi_precache(context, tmp);
        
        if (res < 0) 
                ast_cli(fd, "DUNDi precache returned error.\n");
        else if (!res) 
                ast_cli(fd, "DUNDi precache returned no error.\n");
-       ast_cli(fd, "DUNDi lookup completed in %d ms\n", calc_ms(&start));
+       ast_cli(fd, "DUNDi lookup completed in %d ms\n", ast_tvdiff_ms(ast_tvnow(), start));
        return RESULT_SUCCESS;
 }
 
 static int dundi_do_query(int fd, int argc, char *argv[])
 {
        int res;
-       char tmp[256] = "";
+       char tmp[256];
        char *context;
        dundi_eid eid;
        struct dundi_entity_info dei;
@@ -2353,7 +2362,7 @@ static int dundi_do_query(int fd, int argc, char *argv[])
                ast_cli(fd, "'%s' is not a valid EID!\n", argv[2]);
                return RESULT_SHOWUSAGE;
        }
-       strncpy(tmp, argv[2], sizeof(tmp) - 1);
+       ast_copy_string(tmp, argv[2], sizeof(tmp));
        context = strchr(tmp, '@');
        if (context) {
                *context = '\0';
@@ -2383,18 +2392,15 @@ static int dundi_show_peer(int fd, int argc, char *argv[])
        struct dundi_peer *peer;
        struct permission *p;
        char *order;
-       char iabuf[INET_ADDRSTRLEN];
        char eid_str[20];
        int x, cnt;
        
        if (argc != 4)
                return RESULT_SHOWUSAGE;
-       ast_mutex_lock(&peerlock);
-       peer = peers;
-       while(peer) {
+       AST_LIST_LOCK(&peers);
+       AST_LIST_TRAVERSE(&peers, peer, list) {
                if (!strcasecmp(dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), argv[3]))
                        break;
-               peer = peer->next;
        }
        if (peer) {
                switch(peer->order) {
@@ -2415,30 +2421,21 @@ static int dundi_show_peer(int fd, int argc, char *argv[])
                }
                ast_cli(fd, "Peer:    %s\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
                ast_cli(fd, "Model:   %s\n", model2str(peer->model));
-               ast_cli(fd, "Host:    %s\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "<Unspecified>");
+               ast_cli(fd, "Host:    %s\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "<Unspecified>");
                ast_cli(fd, "Dynamic: %s\n", peer->dynamic ? "yes" : "no");
-               ast_cli(fd, "KeyPend: %s\n", peer->keypending ? "yes" : "no");
                ast_cli(fd, "Reg:     %s\n", peer->registerid < 0 ? "No" : "Yes");
                ast_cli(fd, "In Key:  %s\n", ast_strlen_zero(peer->inkey) ? "<None>" : peer->inkey);
                ast_cli(fd, "Out Key: %s\n", ast_strlen_zero(peer->outkey) ? "<None>" : peer->outkey);
-               if (peer->include) {
+               if (!AST_LIST_EMPTY(&peer->include))
                        ast_cli(fd, "Include logic%s:\n", peer->model & DUNDI_MODEL_OUTBOUND ? "" : " (IGNORED)");
-               }
-               p = peer->include;
-               while(p) {
+               AST_LIST_TRAVERSE(&peer->include, p, list)
                        ast_cli(fd, "-- %s %s\n", p->allow ? "include" : "do not include", p->name);
-                       p = p->next;
-               }
-               if (peer->permit) {
+               if (!AST_LIST_EMPTY(&peer->permit))
                        ast_cli(fd, "Query logic%s:\n", peer->model & DUNDI_MODEL_INBOUND ? "" : " (IGNORED)");
-               }
-               p = peer->permit;
-               while(p) {
+               AST_LIST_TRAVERSE(&peer->permit, p, list)
                        ast_cli(fd, "-- %s %s\n", p->allow ? "permit" : "deny", p->name);
-                       p = p->next;
-               }
                cnt = 0;
-               for (x=0;x<DUNDI_TIMING_HISTORY;x++) {
+               for (x = 0;x < DUNDI_TIMING_HISTORY; x++) {
                        if (peer->lookups[x]) {
                                if (!cnt)
                                        ast_cli(fd, "Last few query times:\n");
@@ -2450,7 +2447,7 @@ static int dundi_show_peer(int fd, int argc, char *argv[])
                        ast_cli(fd, "Average query time: %d ms\n", peer->avgms);
        } else
                ast_cli(fd, "No such peer '%s'\n", argv[3]);
-       ast_mutex_unlock(&peerlock);
+       AST_LIST_UNLOCK(&peers);
        return RESULT_SUCCESS;
 }
 
@@ -2459,10 +2456,14 @@ static int dundi_show_peers(int fd, int argc, char *argv[])
 #define FORMAT2 "%-20.20s %-15.15s     %-10.10s %-8.8s %-15.15s\n"
 #define FORMAT "%-20.20s %-15.15s %s %-10.10s %-8.8s %-15.15s\n"
        struct dundi_peer *peer;
-       char iabuf[INET_ADDRSTRLEN];
        int registeredonly=0;
        char avgms[20];
        char eid_str[20];
+       int online_peers = 0;
+       int offline_peers = 0;
+       int unmonitored_peers = 0;
+       int total_peers = 0;
+
        if ((argc != 3) && (argc != 4) && (argc != 5))
                return RESULT_SHOWUSAGE;
        if ((argc == 4)) {
@@ -2471,31 +2472,42 @@ static int dundi_show_peers(int fd, int argc, char *argv[])
                } else
                        return RESULT_SHOWUSAGE;
        }
-       ast_mutex_lock(&peerlock);
+       AST_LIST_LOCK(&peers);
        ast_cli(fd, FORMAT2, "EID", "Host", "Model", "AvgTime", "Status");
-       for (peer = peers;peer;peer = peer->next) {
-               char status[20] = "";
-        int print_line = -1;
-               char srch[2000] = "";
+       AST_LIST_TRAVERSE(&peers, peer, list) {
+               char status[20];
+               int print_line = -1;
+               char srch[2000];
+               total_peers++;
                if (registeredonly && !peer->addr.sin_addr.s_addr)
                        continue;
                if (peer->maxms) {
-                       if (peer->lastms < 0)
-                               strncpy(status, "UNREACHABLE", sizeof(status) - 1);
-                       else if (peer->lastms > peer->maxms) 
+                       if (peer->lastms < 0) {
+                               strcpy(status, "UNREACHABLE");
+                               offline_peers++;
+                       }
+                       else if (peer->lastms > peer->maxms) {
                                snprintf(status, sizeof(status), "LAGGED (%d ms)", peer->lastms);
-                       else if (peer->lastms) 
+                               offline_peers++;
+                       }
+                       else if (peer->lastms) {
                                snprintf(status, sizeof(status), "OK (%d ms)", peer->lastms);
-                       else 
-                               strncpy(status, "UNKNOWN", sizeof(status) - 1);
-               } else 
-                       strncpy(status, "Unmonitored", sizeof(status) - 1);
+                               online_peers++;
+                       }
+                       else {
+                               strcpy(status, "UNKNOWN");
+                               offline_peers++;
+                       }
+               } else {
+                       strcpy(status, "Unmonitored");
+                       unmonitored_peers++;
+               }
                if (peer->avgms) 
                        snprintf(avgms, sizeof(avgms), "%d ms", peer->avgms);
                else
                        strcpy(avgms, "Unavail");
                snprintf(srch, sizeof(srch), FORMAT, dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), 
-                                       peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "(Unspecified)",
+                                       peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
                                        peer->dynamic ? "(D)" : "(S)", model2str(peer->model), avgms, status);
 
                 if (argc == 5) {
@@ -2512,11 +2524,12 @@ static int dundi_show_peers(int fd, int argc, char *argv[])
                
         if (print_line) {
                        ast_cli(fd, FORMAT, dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), 
-                                       peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "(Unspecified)",
+                                       peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
                                        peer->dynamic ? "(D)" : "(S)", model2str(peer->model), avgms, status);
                }
        }
-       ast_mutex_unlock(&peerlock);
+       ast_cli(fd, "%d dundi peers [%d online, %d offline, %d unmonitored]\n", total_peers, online_peers, offline_peers, unmonitored_peers);
+       AST_LIST_UNLOCK(&peers);
        return RESULT_SUCCESS;
 #undef FORMAT
 #undef FORMAT2
@@ -2527,16 +2540,15 @@ static int dundi_show_trans(int fd, int argc, char *argv[])
 #define FORMAT2 "%-22.22s %-5.5s %-5.5s %-3.3s %-3.3s %-3.3s\n"
 #define FORMAT "%-16.16s:%5d %-5.5d %-5.5d %-3.3d %-3.3d %-3.3d\n"
        struct dundi_transaction *trans;
-       char iabuf[INET_ADDRSTRLEN];
        if (argc != 3)
                return RESULT_SHOWUSAGE;
-       ast_mutex_lock(&peerlock);
+       AST_LIST_LOCK(&peers);
        ast_cli(fd, FORMAT2, "Remote", "Src", "Dst", "Tx", "Rx", "Ack");
-       for (trans = alltrans;trans;trans = trans->allnext) {
-                       ast_cli(fd, FORMAT, ast_inet_ntoa(iabuf, sizeof(iabuf), trans->addr.sin_addr), 
-                                       ntohs(trans->addr.sin_port), trans->strans, trans->dtrans, trans->oseqno, trans->iseqno, trans->aseqno);
+       AST_LIST_TRAVERSE(&alltrans, trans, all) {
+               ast_cli(fd, FORMAT, ast_inet_ntoa(trans->addr.sin_addr), 
+                       ntohs(trans->addr.sin_port), trans->strans, trans->dtrans, trans->oseqno, trans->iseqno, trans->aseqno);
        }
-       ast_mutex_unlock(&peerlock);
+       AST_LIST_UNLOCK(&peers);
        return RESULT_SUCCESS;
 #undef FORMAT
 #undef FORMAT2
@@ -2547,9 +2559,9 @@ static int dundi_show_entityid(int fd, int argc, char *argv[])
        char eid_str[20];
        if (argc != 3)
                return RESULT_SHOWUSAGE;
-       ast_mutex_lock(&peerlock);
+       AST_LIST_LOCK(&peers);
        dundi_eid_to_str(eid_str, sizeof(eid_str), &global_eid);
-       ast_mutex_unlock(&peerlock);
+       AST_LIST_UNLOCK(&peers);
        ast_cli(fd, "Global EID for this system is '%s'\n", eid_str);
        return RESULT_SUCCESS;
 }
@@ -2562,13 +2574,13 @@ static int dundi_show_requests(int fd, int argc, char *argv[])
        char eidstr[20];
        if (argc != 3)
                return RESULT_SHOWUSAGE;
-       ast_mutex_lock(&peerlock);
+       AST_LIST_LOCK(&peers);
        ast_cli(fd, FORMAT2, "Number", "Context", "Root", "Max", "Rsp");
-       for (req = requests;req;req = req->next) {
-                       ast_cli(fd, FORMAT, req->number, req->dcontext,
-                                               dundi_eid_zero(&req->root_eid) ? "<unspecified>" : dundi_eid_to_str(eidstr, sizeof(eidstr), &req->root_eid), req->maxcount, req->respcount);
+       AST_LIST_TRAVERSE(&requests, req, list) {
+               ast_cli(fd, FORMAT, req->number, req->dcontext,
+                       dundi_eid_zero(&req->root_eid) ? "<unspecified>" : dundi_eid_to_str(eidstr, sizeof(eidstr), &req->root_eid), req->maxcount, req->respcount);
        }
-       ast_mutex_unlock(&peerlock);
+       AST_LIST_UNLOCK(&peers);
        return RESULT_SUCCESS;
 #undef FORMAT
 #undef FORMAT2
@@ -2584,14 +2596,14 @@ static int dundi_show_mappings(int fd, int argc, char *argv[])
        char fs[256];
        if (argc != 3)
                return RESULT_SHOWUSAGE;
-       ast_mutex_lock(&peerlock);
+       AST_LIST_LOCK(&peers);
        ast_cli(fd, FORMAT2, "DUNDi Cntxt", "Weight", "Local Cntxt", "Options", "Tech", "Destination");
-       for (map = mappings;map;map = map->next) {
-                       ast_cli(fd, FORMAT, map->dcontext, map->weight, 
-                                           ast_strlen_zero(map->lcontext) ? "<none>" : map->lcontext, 
-                                                               dundi_flags2str(fs, sizeof(fs), map->options), tech2str(map->tech), map->dest);
+       AST_LIST_TRAVERSE(&mappings, map, list) {
+               ast_cli(fd, FORMAT, map->dcontext, map->weight, 
+                       ast_strlen_zero(map->lcontext) ? "<none>" : map->lcontext, 
+                       dundi_flags2str(fs, sizeof(fs), map->options), tech2str(map->tech), map->dest);
        }
-       ast_mutex_unlock(&peerlock);
+       AST_LIST_UNLOCK(&peers);
        return RESULT_SUCCESS;
 #undef FORMAT
 #undef FORMAT2
@@ -2608,9 +2620,9 @@ static int dundi_show_precache(int fd, int argc, char *argv[])
        if (argc != 3)
                return RESULT_SHOWUSAGE;
        time(&now);
-       ast_mutex_lock(&pclock);
        ast_cli(fd, FORMAT2, "Number", "Context", "Expiration");
-       for (qe = pcq;qe;qe = qe->next) {
+       AST_LIST_LOCK(&pcq);
+       AST_LIST_TRAVERSE(&pcq, qe, list) {
                s = qe->expiration - now;
                h = s / 3600;
                s = s % 3600;
@@ -2618,130 +2630,144 @@ static int dundi_show_precache(int fd, int argc, char *argv[])
                s = s % 60;
                ast_cli(fd, FORMAT, qe->number, qe->context, h,m,s);
        }
-       ast_mutex_unlock(&pclock);
+       AST_LIST_UNLOCK(&pcq);
+       
        return RESULT_SUCCESS;
 #undef FORMAT
 #undef FORMAT2
 }
 
-static char debug_usage[] = 
+static const char debug_usage[] = 
 "Usage: dundi debug\n"
 "       Enables dumping of DUNDi packets for debugging purposes\n";
 
-static char no_debug_usage[] = 
+static const char no_debug_usage[] = 
 "Usage: dundi no debug\n"
 "       Disables dumping of DUNDi packets for debugging purposes\n";
 
-static char store_history_usage[] = 
+static const char store_history_usage[] = 
 "Usage: dundi store history\n"
 "       Enables storing of DUNDi requests and times for debugging\n"
 "purposes\n";
 
-static char no_store_history_usage[] = 
+static const char no_store_history_usage[] = 
 "Usage: dundi no store history\n"
 "       Disables storing of DUNDi requests and times for debugging\n"
 "purposes\n";
 
-static char show_peers_usage[] = 
+static const char show_peers_usage[] = 
 "Usage: dundi show peers\n"
 "       Lists all known DUNDi peers.\n";
 
-static char show_trans_usage[] = 
+static const char show_trans_usage[] = 
 "Usage: dundi show trans\n"
 "       Lists all known DUNDi transactions.\n";
 
-static char show_mappings_usage[] = 
+static const char show_mappings_usage[] = 
 "Usage: dundi show mappings\n"
 "       Lists all known DUNDi mappings.\n";
 
-static char show_precache_usage[] = 
+static const char show_precache_usage[] = 
 "Usage: dundi show precache\n"
 "       Lists all known DUNDi scheduled precache updates.\n";
 
-static char show_entityid_usage[] = 
+static const char show_entityid_usage[] = 
 "Usage: dundi show entityid\n"
 "       Displays the global entityid for this host.\n";
 
-static char show_peer_usage[] = 
+static const char show_peer_usage[] = 
 "Usage: dundi show peer [peer]\n"
 "       Provide a detailed description of a specifid DUNDi peer.\n";
 
-static char show_requests_usage[] = 
+static const char show_requests_usage[] = 
 "Usage: dundi show requests\n"
 "       Lists all known pending DUNDi requests.\n";
 
-static char lookup_usage[] =
+static const char lookup_usage[] =
 "Usage: dundi lookup <number>[@context] [bypass]\n"
 "       Lookup the given number within the given DUNDi context\n"
 "(or e164 if none is specified).  Bypasses cache if 'bypass'\n"
 "keyword is specified.\n";
 
-static char precache_usage[] =
+static const char precache_usage[] =
 "Usage: dundi precache <number>[@context]\n"
 "       Lookup the given number within the given DUNDi context\n"
 "(or e164 if none is specified) and precaches the results to any\n"
 "upstream DUNDi push servers.\n";
 
-static char query_usage[] =
+static const char query_usage[] =
 "Usage: dundi query <entity>[@context]\n"
 "       Attempts to retrieve contact information for a specific\n"
 "DUNDi entity identifier (EID) within a given DUNDi context (or\n"
 "e164 if none is specified).\n";
 
-static char flush_usage[] =
+static const char flush_usage[] =
 "Usage: dundi flush [stats]\n"
 "       Flushes DUNDi answer cache, used primarily for debug.  If\n"
 "'stats' is present, clears timer statistics instead of normal\n"
 "operation.\n";
 
-static struct ast_cli_entry  cli_debug =
-       { { "dundi", "debug", NULL }, dundi_do_debug, "Enable DUNDi debugging", debug_usage };
+static struct ast_cli_entry cli_dundi[] = {
+       { { "dundi", "debug", NULL },
+       dundi_do_debug, "Enable DUNDi debugging",
+       debug_usage },
 
-static struct ast_cli_entry  cli_store_history =
-       { { "dundi", "store", "history", NULL }, dundi_do_store_history, "Enable DUNDi historic records", store_history_usage };
+       { { "dundi", "store", "history", NULL },
+       dundi_do_store_history, "Enable DUNDi historic records",
+       store_history_usage },
 
-static struct ast_cli_entry  cli_no_store_history =
-       { { "dundi", "no", "store", "history", NULL }, dundi_no_store_history, "Disable DUNDi historic records", no_store_history_usage };
+       { { "dundi", "no", "store", "history", NULL },
+       dundi_no_store_history, "Disable DUNDi historic records",
+       no_store_history_usage },
 
-static struct ast_cli_entry  cli_flush =
-       { { "dundi", "flush", NULL }, dundi_flush, "Flush DUNDi cache", flush_usage };
+       { { "dundi", "flush", NULL },
+       dundi_flush, "Flush DUNDi cache",
+       flush_usage },
 
-static struct ast_cli_entry  cli_no_debug =
-       { { "dundi", "no", "debug", NULL }, dundi_no_debug, "Disable DUNDi debugging", no_debug_usage };
+       { { "dundi", "no", "debug", NULL },
+       dundi_no_debug, "Disable DUNDi debugging",
+       no_debug_usage },
 
-static struct ast_cli_entry  cli_show_peers =
-       { { "dundi", "show", "peers", NULL }, dundi_show_peers, "Show defined DUNDi peers", show_peers_usage };
+       { { "dundi", "show", "peers", NULL },
+       dundi_show_peers, "Show defined DUNDi peers",
+       show_peers_usage },
 
-static struct ast_cli_entry  cli_show_trans =
-       { { "dundi", "show", "trans", NULL }, dundi_show_trans, "Show active DUNDi transactions", show_trans_usage };
+       { { "dundi", "show", "trans", NULL },
+       dundi_show_trans, "Show active DUNDi transactions",
+       show_trans_usage },
 
-static struct ast_cli_entry  cli_show_entityid =
-       { { "dundi", "show", "entityid", NULL }, dundi_show_entityid, "Display Global Entity ID", show_entityid_usage };
+       { { "dundi", "show", "entityid", NULL },
+       dundi_show_entityid, "Display Global Entity ID",
+       show_entityid_usage },
 
-static struct ast_cli_entry  cli_show_mappings =
-       { { "dundi", "show", "mappings", NULL }, dundi_show_mappings, "Show DUNDi mappings", show_mappings_usage };
+       { { "dundi", "show", "mappings", NULL },
+       dundi_show_mappings, "Show DUNDi mappings",
+       show_mappings_usage },
 
-static struct ast_cli_entry  cli_show_precache =
-       { { "dundi", "show", "precache", NULL }, dundi_show_precache, "Show DUNDi precache", show_precache_usage };
+       { { "dundi", "show", "precache", NULL },
+       dundi_show_precache, "Show DUNDi precache",
+       show_precache_usage },
 
-static struct ast_cli_entry  cli_show_requests =
-       { { "dundi", "show", "requests", NULL }, dundi_show_requests, "Show DUNDi requests", show_requests_usage };
+       { { "dundi", "show", "requests", NULL },
+       dundi_show_requests, "Show DUNDi requests",
+       show_requests_usage },
 
-static struct ast_cli_entry  cli_show_peer =
-       { { "dundi", "show", "peer", NULL }, dundi_show_peer, "Show info on a specific DUNDi peer", show_peer_usage, complete_peer_4 };
+       { { "dundi", "show", "peer", NULL },
+       dundi_show_peer, "Show info on a specific DUNDi peer",
+       show_peer_usage, complete_peer_4 },
 
-static struct ast_cli_entry  cli_lookup =
-       { { "dundi", "lookup", NULL }, dundi_do_lookup, "Lookup a number in DUNDi", lookup_usage };
+       { { "dundi", "lookup", NULL },
+       dundi_do_lookup, "Lookup a number in DUNDi",
+       lookup_usage },
 
-static struct ast_cli_entry  cli_precache =
-       { { "dundi", "precache", NULL }, dundi_do_precache, "Precache a number in DUNDi", precache_usage };
+       { { "dundi", "precache", NULL },
+       dundi_do_precache, "Precache a number in DUNDi",
+       precache_usage },
 
-static struct ast_cli_entry  cli_queryeid =
-       { { "dundi", "query", NULL }, dundi_do_query, "Query a DUNDi EID", query_usage };
-
-STANDARD_LOCAL_USER;
-
-LOCAL_USER_DECL;
+       { { "dundi", "query", NULL },
+       dundi_do_query, "Query a DUNDi EID",
+       query_usage },
+};
 
 static struct dundi_transaction *create_transaction(struct dundi_peer *p)
 {
@@ -2754,37 +2780,35 @@ static struct dundi_transaction *create_transaction(struct dundi_peer *p)
        tid = get_trans_id();
        if (tid < 1)
                return NULL;
-       trans = malloc(sizeof(struct dundi_transaction));
-       if (trans) {
-               memset(trans, 0, sizeof(struct dundi_transaction));
-               if (global_storehistory) {
-                       gettimeofday(&trans->start, NULL);
-                       trans->flags |= FLAG_STOREHIST;
-               }
-               trans->retranstimer = DUNDI_DEFAULT_RETRANS_TIMER;
-               trans->autokillid = -1;
-               if (p) {
-                       apply_peer(trans, p);
-                       if (!p->sentfullkey)
-                               trans->flags |= FLAG_SENDFULLKEY;
-               }
-               trans->strans = tid;
-               trans->allnext = alltrans;
-               alltrans = trans;
+       if (!(trans = ast_calloc(1, sizeof(*trans))))
+               return NULL;
+
+       if (global_storehistory) {
+               trans->start = ast_tvnow();
+               ast_set_flag(trans, FLAG_STOREHIST);
+       }
+       trans->retranstimer = DUNDI_DEFAULT_RETRANS_TIMER;
+       trans->autokillid = -1;
+       if (p) {
+               apply_peer(trans, p);
+               if (!p->sentfullkey)
+                       ast_set_flag(trans, FLAG_SENDFULLKEY);
        }
+       trans->strans = tid;
+       AST_LIST_INSERT_HEAD(&alltrans, trans, all);
+       
        return trans;
 }
 
 static int dundi_xmit(struct dundi_packet *pack)
 {
        int res;
-       char iabuf[INET_ADDRSTRLEN];
        if (dundidebug)
                dundi_showframe(pack->h, 0, &pack->parent->addr, pack->datalen - sizeof(struct dundi_hdr));
        res = sendto(netsocket, pack->data, pack->datalen, 0, (struct sockaddr *)&pack->parent->addr, sizeof(pack->parent->addr));
        if (res < 0) {
                ast_log(LOG_WARNING, "Failed to transmit to '%s:%d': %s\n", 
-                       ast_inet_ntoa(iabuf, sizeof(iabuf), pack->parent->addr.sin_addr),
+                       ast_inet_ntoa(pack->parent->addr.sin_addr),
                        ntohs(pack->parent->addr.sin_port), strerror(errno));
        }
        if (res > 0)
@@ -2794,57 +2818,34 @@ static int dundi_xmit(struct dundi_packet *pack)
 
 static void destroy_packet(struct dundi_packet *pack, int needfree)
 {
-       struct dundi_packet *prev, *cur;
-       if (pack->parent) {
-               prev = NULL;
-               cur = pack->parent->packets;
-               while(cur) {
-                       if (cur == pack) {
-                               if (prev)
-                                       prev->next = cur->next;
-                               else
-                                       pack->parent->packets = cur->next;
-                               break;
-                       }
-                       prev = cur;
-                       cur = cur->next;
-               }
-       }
+       if (pack->parent)
+               AST_LIST_REMOVE(&pack->parent->packets, pack, list);
        if (pack->retransid > -1)
                ast_sched_del(sched, pack->retransid);
        if (needfree)
                free(pack);
-       else {
+       else
                pack->retransid = -1;
-               pack->next = NULL;
-       }
 }
 
 static void destroy_trans(struct dundi_transaction *trans, int fromtimeout)
 {
-       struct dundi_transaction *cur, *prev;
        struct dundi_peer *peer;
-       struct timeval tv;
        int ms;
        int x;
        int cnt;
        char eid_str[20];
-       if (trans->flags & (FLAG_ISREG | FLAG_ISQUAL | FLAG_STOREHIST)) {
-               peer = peers;
-               while (peer) {
+       if (ast_test_flag(trans, FLAG_ISREG | FLAG_ISQUAL | FLAG_STOREHIST)) {
+               AST_LIST_TRAVERSE(&peers, peer, list) {
                        if (peer->regtrans == trans)
                                peer->regtrans = NULL;
-                       if (peer->keypending == trans)
-                               peer->keypending = NULL;
                        if (peer->qualtrans == trans) {
                                if (fromtimeout) {
                                        if (peer->lastms > -1)
                                                ast_log(LOG_NOTICE, "Peer '%s' has become UNREACHABLE!\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
                                        peer->lastms = -1;
                                } else {
-                                       gettimeofday(&tv, NULL);
-                                       ms = (tv.tv_sec - peer->qualtx.tv_sec) * 1000 + 
-                                                       (tv.tv_usec - peer->qualtx.tv_usec) / 1000;
+                                       ms = ast_tvdiff_ms(ast_tvnow(), peer->qualtx);
                                        if (ms < 1)
                                                ms = 1;
                                        if (ms < peer->maxms) {
@@ -2857,7 +2858,7 @@ static void destroy_trans(struct dundi_transaction *trans, int fromtimeout)
                                }
                                peer->qualtrans = NULL;
                        }
-                       if (trans->flags & FLAG_STOREHIST) {
+                       if (ast_test_flag(trans, FLAG_STOREHIST)) {
                                if (trans->parent && !ast_strlen_zero(trans->parent->number)) {
                                        if (!dundi_eid_cmp(&trans->them_eid, &peer->eid)) {
                                                peer->avgms = 0;
@@ -2872,8 +2873,8 @@ static void destroy_trans(struct dundi_transaction *trans, int fromtimeout)
                                                                cnt++;
                                                        }
                                                }
-                                               peer->lookuptimes[0] = calc_ms(&trans->start);
-                                               peer->lookups[0] = malloc(strlen(trans->parent->number) + strlen(trans->parent->dcontext) + 2);
+                                               peer->lookuptimes[0] = ast_tvdiff_ms(ast_tvnow(), trans->start);
+                                               peer->lookups[0] = ast_malloc(strlen(trans->parent->number) + strlen(trans->parent->dcontext) + 2);
                                                if (peer->lookups[0]) {
                                                        sprintf(peer->lookups[0], "%s@%s", trans->parent->number, trans->parent->dcontext);
                                                        peer->avgms += peer->lookuptimes[0];
@@ -2884,25 +2885,12 @@ static void destroy_trans(struct dundi_transaction *trans, int fromtimeout)
                                        }
                                }
                        }
-                       peer = peer->next;
                }
        }
        if (trans->parent) {
                /* Unlink from parent if appropriate */
-               prev = NULL;
-               cur = trans->parent->trans;
-               while(cur) {
-                       if (cur == trans) {
-                               if (prev)
-                                       prev->next = trans->next;
-                               else
-                                       trans->parent->trans = trans->next;
-                               break;
-                       }
-                       prev = cur;
-                       cur = cur->next;
-               }
-               if (!trans->parent->trans) {
+               AST_LIST_REMOVE(&trans->parent->trans, trans, parentlist);
+               if (AST_LIST_EMPTY(&trans->parent->trans)) {
                        /* Wake up sleeper */
                        if (trans->parent->pfds[1] > -1) {
                                write(trans->parent->pfds[1], "killa!", 6);
@@ -2910,28 +2898,15 @@ static void destroy_trans(struct dundi_transaction *trans, int fromtimeout)
                }
        }
        /* Unlink from all trans */
-       prev = NULL;
-       cur = alltrans;
-       while(cur) {
-               if (cur == trans) {
-                       if (prev)
-                               prev->allnext = trans->allnext;
-                       else
-                               alltrans = trans->allnext;
-                       break;
-               }
-               prev = cur;
-               cur = cur->allnext;
-       }
-       destroy_packets(trans->packets);
-       destroy_packets(trans->lasttrans);
-       trans->packets = NULL;
+       AST_LIST_REMOVE(&alltrans, trans, all);
+       destroy_packets(&trans->packets);
+       destroy_packets(&trans->lasttrans);
        if (trans->autokillid > -1)
                ast_sched_del(sched, trans->autokillid);
        trans->autokillid = -1;
        if (trans->thread) {
                /* If used by a thread, mark as dead and be done */
-               trans->flags |= FLAG_DEAD;
+               ast_set_flag(trans, FLAG_DEAD);
        } else
                free(trans);
 }
@@ -2939,15 +2914,14 @@ static void destroy_trans(struct dundi_transaction *trans, int fromtimeout)
 static int dundi_rexmit(void *data)
 {
        struct dundi_packet *pack;
-       char iabuf[INET_ADDRSTRLEN];
        int res;
-       ast_mutex_lock(&peerlock);
+       AST_LIST_LOCK(&peers);
        pack = data;
        if (pack->retrans < 1) {
                pack->retransid = -1;
-               if (!(pack->parent->flags & FLAG_ISQUAL))
+               if (!ast_test_flag(pack->parent, FLAG_ISQUAL))
                        ast_log(LOG_NOTICE, "Max retries exceeded to host '%s:%d' msg %d on call %d\n", 
-                               ast_inet_ntoa(iabuf, sizeof(iabuf), pack->parent->addr.sin_addr), 
+                               ast_inet_ntoa(pack->parent->addr.sin_addr), 
                                ntohs(pack->parent->addr.sin_port), pack->h->oseqno, ntohs(pack->h->strans));
                destroy_trans(pack->parent, 1);
                res = 0;
@@ -2957,7 +2931,7 @@ static int dundi_rexmit(void *data)
                dundi_xmit(pack);
                res = 1;
        }
-       ast_mutex_unlock(&peerlock);
+       AST_LIST_UNLOCK(&peers);
        return res;
 }
 
@@ -2969,17 +2943,15 @@ static int dundi_send(struct dundi_transaction *trans, int cmdresp, int flags, i
        char eid_str[20];
        len = sizeof(struct dundi_packet) + sizeof(struct dundi_hdr) + (ied ? ied->pos : 0);
        /* Reserve enough space for encryption */
-       if (trans->flags & FLAG_ENCRYPT)
+       if (ast_test_flag(trans, FLAG_ENCRYPT))
                len += 384;
-       pack = malloc(len);
+       pack = ast_calloc(1, len);
        if (pack) {
-               memset(pack, 0, len);
                pack->h = (struct dundi_hdr *)(pack->data);
                if (cmdresp != DUNDI_COMMAND_ACK) {
                        pack->retransid = ast_sched_add(sched, trans->retranstimer, dundi_rexmit, pack);
                        pack->retrans = DUNDI_DEFAULT_RETRANS - 1;
-                       pack->next = trans->packets;
-                       trans->packets = pack;
+                       AST_LIST_INSERT_HEAD(&trans->packets, pack, list);
                }
                pack->parent = trans;
                pack->h->strans = htons(trans->strans);
@@ -2994,7 +2966,7 @@ static int dundi_send(struct dundi_transaction *trans, int cmdresp, int flags, i
                } 
                if (final) {
                        pack->h->cmdresp |= DUNDI_COMMAND_FINAL;
-                       trans->flags |= FLAG_FINAL;
+                       ast_set_flag(trans, FLAG_FINAL);
                }
                pack->h->cmdflags = flags;
                if (cmdresp != DUNDI_COMMAND_ACK) {
@@ -3003,7 +2975,7 @@ static int dundi_send(struct dundi_transaction *trans, int cmdresp, int flags, i
                }
                trans->aseqno = trans->iseqno;
                /* If we have their public key, encrypt */
-               if (trans->flags & FLAG_ENCRYPT) {
+               if (ast_test_flag(trans, FLAG_ENCRYPT)) {
                        switch(cmdresp) {
                        case DUNDI_COMMAND_REGREQ:
                        case DUNDI_COMMAND_REGRESPONSE:
@@ -3052,21 +3024,19 @@ static void dundi_ie_append_eid_appropriately(struct dundi_ie_data *ied, char *c
                dundi_ie_append_eid(ied, DUNDI_IE_EID_DIRECT, eid);
                return;
        }
-       ast_mutex_lock(&peerlock);
-       p = peers;
-       while(p) {
+       AST_LIST_LOCK(&peers);
+       AST_LIST_TRAVERSE(&peers, p, list) {
                if (!dundi_eid_cmp(&p->eid, eid)) {
-                       if (has_permission(p->include, context))
+                       if (has_permission(&p->include, context))
                                dundi_ie_append_eid(ied, DUNDI_IE_EID_DIRECT, eid);
                        else
                                dundi_ie_append_eid(ied, DUNDI_IE_EID, eid);
                        break;
                }
-               p = p->next;
        }
        if (!p)
                dundi_ie_append_eid(ied, DUNDI_IE_EID, eid);
-       ast_mutex_unlock(&peerlock);
+       AST_LIST_UNLOCK(&peers);
 }
 
 static int dundi_discover(struct dundi_transaction *trans)
@@ -3098,7 +3068,7 @@ static int precache_trans(struct dundi_transaction *trans, struct dundi_mapping
        struct dundi_ie_data ied;
        int x, res;
        int max = 999999;
-       int expiration = DUNDI_DEFAULT_CACHE_TIME;
+       int expiration = dundi_cache_time;
        int ouranswers=0;
        dundi_eid *avoid[1] = { NULL, };
        int direct[1] = { 0, };
@@ -3184,63 +3154,60 @@ static int dundi_query(struct dundi_transaction *trans)
 static int discover_transactions(struct dundi_request *dr)
 {
        struct dundi_transaction *trans;
-       ast_mutex_lock(&peerlock);
-       trans = dr->trans;
-       while(trans) {
+       AST_LIST_LOCK(&peers);
+       AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) {
                dundi_discover(trans);
-               trans = trans->next;
        }
-       ast_mutex_unlock(&peerlock);
+       AST_LIST_UNLOCK(&peers);
        return 0;
 }
 
 static int precache_transactions(struct dundi_request *dr, struct dundi_mapping *maps, int mapcount, int *expiration, int *foundanswers)
 {
-       struct dundi_transaction *trans, *transn;
+       struct dundi_transaction *trans;
+
        /* Mark all as "in thread" so they don't disappear */
-       ast_mutex_lock(&peerlock);
-       trans = dr->trans;
-       while(trans) {
+       AST_LIST_LOCK(&peers);
+       AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) {
                if (trans->thread)
                        ast_log(LOG_WARNING, "This shouldn't happen, really...\n");
                trans->thread = 1;
-               trans = trans->next;
        }
-       ast_mutex_unlock(&peerlock);
+       AST_LIST_UNLOCK(&peers);
 
-       trans = dr->trans;
-       while(trans) {
-               if (!(trans->flags & FLAG_DEAD))
+       AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) {
+               if (!ast_test_flag(trans, FLAG_DEAD))
                        precache_trans(trans, maps, mapcount, expiration, foundanswers);
-               trans = trans->next;
        }
 
        /* Cleanup any that got destroyed in the mean time */
-       ast_mutex_lock(&peerlock);
-       trans = dr->trans;
-       while(trans) {
-               transn = trans->next;
+       AST_LIST_LOCK(&peers);
+       AST_LIST_TRAVERSE_SAFE_BEGIN(&dr->trans, trans, parentlist) {
                trans->thread = 0;
-               if (trans->flags & FLAG_DEAD) {
-                       ast_log(LOG_DEBUG, "Our transaction went away!\n");
+               if (ast_test_flag(trans, FLAG_DEAD)) {
+                       if (option_debug)
+                               ast_log(LOG_DEBUG, "Our transaction went away!\n");
+                       /* This is going to remove the transaction from the dundi_request's list, as well
+                        * as the global transactions list */
                        destroy_trans(trans, 0);
                }
-               trans = transn;
        }
-       ast_mutex_unlock(&peerlock);
+       AST_LIST_TRAVERSE_SAFE_END
+       AST_LIST_UNLOCK(&peers);
+
        return 0;
 }
 
 static int query_transactions(struct dundi_request *dr)
 {
        struct dundi_transaction *trans;
-       ast_mutex_lock(&peerlock);
-       trans = dr->trans;
-       while(trans) {
+
+       AST_LIST_LOCK(&peers);
+       AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) {
                dundi_query(trans);
-               trans = trans->next;
        }
-       ast_mutex_unlock(&peerlock);
+       AST_LIST_UNLOCK(&peers);
+
        return 0;
 }
 
@@ -3253,9 +3220,9 @@ static int optimize_transactions(struct dundi_request *dr, int order)
        dundi_eid tmp;
        int x;
        int needpush;
-       ast_mutex_lock(&peerlock);
-       trans = dr->trans;
-       while(trans) {
+
+       AST_LIST_LOCK(&peers);
+       AST_LIST_TRAVERSE(&dr->trans, trans, parentlist) {
                /* Pop off the true root */
                if (trans->eidcount) {
                        tmp = trans->eids[--trans->eidcount];
@@ -3265,9 +3232,8 @@ static int optimize_transactions(struct dundi_request *dr, int order)
                        needpush = 0;
                }
 
-               peer = peers;
-               while(peer) {
-                       if (has_permission(peer->include, dr->dcontext) && 
+               AST_LIST_TRAVERSE(&peers, peer, list) {
+                       if (has_permission(&peer->include, dr->dcontext) && 
                            dundi_eid_cmp(&peer->eid, &trans->them_eid) &&
                                (peer->order <= order)) {
                                /* For each other transaction, make sure we don't
@@ -3291,14 +3257,13 @@ static int optimize_transactions(struct dundi_request *dr, int order)
                                        }
                                }
                        }
-                       peer = peer->next;
                }
                /* If necessary, push the true root back on the end */
                if (needpush)
                        trans->eids[trans->eidcount++] = tmp;
-               trans = trans->next;
        }
-       ast_mutex_unlock(&peerlock);
+       AST_LIST_UNLOCK(&peers);
+
        return 0;
 }
 
@@ -3308,53 +3273,57 @@ static int append_transaction(struct dundi_request *dr, struct dundi_peer *p, in
        int x;
        char eid_str[20];
        char eid_str2[20];
+
        /* Ignore if not registered */
        if (!p->addr.sin_addr.s_addr)
                return 0;
        if (p->maxms && ((p->lastms < 0) || (p->lastms >= p->maxms)))
                return 0;
-       if (ast_strlen_zero(dr->number))
-               ast_log(LOG_DEBUG, "Will query peer '%s' for '%s' (context '%s')\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &p->eid), dundi_eid_to_str(eid_str2, sizeof(eid_str2), &dr->query_eid), dr->dcontext);
-       else
-               ast_log(LOG_DEBUG, "Will query peer '%s' for '%s@%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &p->eid), dr->number, dr->dcontext);
+
+       if (option_debug) {
+               if (ast_strlen_zero(dr->number))
+                       ast_log(LOG_DEBUG, "Will query peer '%s' for '%s' (context '%s')\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &p->eid), dundi_eid_to_str(eid_str2, sizeof(eid_str2), &dr->query_eid), dr->dcontext);
+               else
+                       ast_log(LOG_DEBUG, "Will query peer '%s' for '%s@%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &p->eid), dr->number, dr->dcontext);
+       }
+
        trans = create_transaction(p);
        if (!trans)
                return -1;
-       trans->next = dr->trans;
        trans->parent = dr;
        trans->ttl = ttl;
-       for (x=0;avoid[x] && (x <DUNDI_MAX_STACK);x++)
+       for (x = 0; avoid[x] && (x < DUNDI_MAX_STACK); x++)
                trans->eids[x] = *avoid[x];
        trans->eidcount = x;
-       dr->trans = trans;
+       AST_LIST_INSERT_HEAD(&dr->trans, trans, parentlist);
+       
        return 0;
 }
 
 static void cancel_request(struct dundi_request *dr)
 {
-       struct dundi_transaction *trans, *next;
+       struct dundi_transaction *trans;
 
-       ast_mutex_lock(&peerlock);
-       trans = dr->trans;
-       
-       while(trans) {
-               next = trans->next;
+       AST_LIST_LOCK(&peers);
+       while ((trans = AST_LIST_REMOVE_HEAD(&dr->trans, parentlist))) {
                /* Orphan transaction from request */
                trans->parent = NULL;
-               trans->next = NULL;
                /* Send final cancel */
                dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
-               trans = next;
        }
-       ast_mutex_unlock(&peerlock);
+       AST_LIST_UNLOCK(&peers);
 }
 
 static void abort_request(struct dundi_request *dr)
 {
-       ast_mutex_lock(&peerlock);
-       while(dr->trans) 
-               destroy_trans(dr->trans, 0);
-       ast_mutex_unlock(&peerlock);
+       struct dundi_transaction *trans;
+
+       AST_LIST_LOCK(&peers);
+       while ((trans = AST_LIST_FIRST(&dr->trans))) {
+               /* This will remove the transaction from the list */
+               destroy_trans(trans, 0);
+       }
+       AST_LIST_UNLOCK(&peers);
 }
 
 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[])
@@ -3365,16 +3334,15 @@ static void build_transactions(struct dundi_request *dr, int ttl, int order, int
        int pass;
        int allowconnect;
        char eid_str[20];
-       ast_mutex_lock(&peerlock);
-       p = peers;
-       while(p) {
+       AST_LIST_LOCK(&peers);
+       AST_LIST_TRAVERSE(&peers, p, list) {
                if (modeselect == 1) {
                        /* Send the precache to push upstreams only! */
-                       pass = has_permission(p->permit, dr->dcontext) && (p->pcmodel & DUNDI_MODEL_OUTBOUND);
+                       pass = has_permission(&p->permit, dr->dcontext) && (p->pcmodel & DUNDI_MODEL_OUTBOUND);
                        allowconnect = 1;
                } else {
                        /* Normal lookup / EID query */
-                       pass = has_permission(p->include, dr->dcontext);
+                       pass = has_permission(&p->include, dr->dcontext);
                        allowconnect = p->model & DUNDI_MODEL_OUTBOUND;
                }
                if (skip) {
@@ -3394,7 +3362,7 @@ static void build_transactions(struct dundi_request *dr, int ttl, int order, int
                                                if (!dundi_eid_cmp(avoid[x], &p->eid) || !dundi_eid_cmp(avoid[x], &p->us_eid)) {
                                                        /* If not a direct connection, it affects our answer */
                                                        if (directs && !directs[x]) 
-                                                               dr->hmd->flags &= ~DUNDI_HINT_UNAFFECTED;
+                                                               ast_clear_flag_nonstd(dr->hmd, DUNDI_HINT_UNAFFECTED);
                                                        break;
                                                }
                                        }
@@ -3403,17 +3371,18 @@ static void build_transactions(struct dundi_request *dr, int ttl, int order, int
                                                if (!avoid[x] && (!blockempty || !dundi_eid_zero(&p->us_eid))) {
                                                        /* Check for a matching or 0 cache entry */
                                                        append_transaction(dr, p, ttl, avoid);
-                                               } else
-                                                       ast_log(LOG_DEBUG, "Avoiding '%s' in transaction\n", dundi_eid_to_str(eid_str, sizeof(eid_str), avoid[x]));
+                                               } else {
+                                                       if (option_debug)
+                                                               ast_log(LOG_DEBUG, "Avoiding '%s' in transaction\n", dundi_eid_to_str(eid_str, sizeof(eid_str), avoid[x]));
+                                               }
                                        }
                                }
                                *foundcache |= res;
                        } else if (!*skipped || (p->order < *skipped))
                                *skipped = p->order;
                }
-               p = p->next;
        }
-       ast_mutex_unlock(&peerlock);
+       AST_LIST_UNLOCK(&peers);
 }
 
 static int register_request(struct dundi_request *dr, struct dundi_request **pending)
@@ -3421,70 +3390,53 @@ static int register_request(struct dundi_request *dr, struct dundi_request **pen
        struct dundi_request *cur;
        int res=0;
        char eid_str[20];
-       ast_mutex_lock(&peerlock);
-       cur = requests;
-       while(cur) {
+       AST_LIST_LOCK(&peers);
+       AST_LIST_TRAVERSE(&requests, cur, list) {
                if (option_debug)
                        ast_log(LOG_DEBUG, "Checking '%s@%s' vs '%s@%s'\n", cur->dcontext, cur->number,
                                dr->dcontext, dr->number);
                if (!strcasecmp(cur->dcontext, dr->dcontext) &&
                    !strcasecmp(cur->number, dr->number) &&
-                       (!dundi_eid_cmp(&cur->root_eid, &dr->root_eid) || (cur->crc32 == dr->crc32))) {
+                   (!dundi_eid_cmp(&cur->root_eid, &dr->root_eid) || (cur->crc32 == dr->crc32))) {
+                       if (option_debug)
                                ast_log(LOG_DEBUG, "Found existing query for '%s@%s' for '%s' crc '%08lx'\n", 
                                        cur->dcontext, cur->number, dundi_eid_to_str(eid_str, sizeof(eid_str), &cur->root_eid), cur->crc32);
-                               *pending = cur;
+                       *pending = cur;
                        res = 1;
                        break;
                }
-               cur = cur->next;
        }
        if (!res) {
-               ast_log(LOG_DEBUG, "Registering request for '%s@%s' on behalf of '%s' crc '%08lx'\n", 
-                               dr->number, dr->dcontext, dundi_eid_to_str(eid_str, sizeof(eid_str), &dr->root_eid), dr->crc32);
+               if (option_debug)
+                       ast_log(LOG_DEBUG, "Registering request for '%s@%s' on behalf of '%s' crc '%08lx'\n", 
+                                       dr->number, dr->dcontext, dundi_eid_to_str(eid_str, sizeof(eid_str), &dr->root_eid), dr->crc32);
                /* Go ahead and link us in since nobody else is searching for this */
-               dr->next = requests;
-               requests = dr;
+               AST_LIST_INSERT_HEAD(&requests, dr, list);
                *pending = NULL;
        }
-       ast_mutex_unlock(&peerlock);
+       AST_LIST_UNLOCK(&peers);
        return res;
 }
 
 static void unregister_request(struct dundi_request *dr)
 {
-       struct dundi_request *cur, *prev;
-       ast_mutex_lock(&peerlock);
-       prev = NULL;
-       cur = requests;
-       while(cur) {
-               if (cur == dr) {
-                       if (prev)
-                               prev->next = cur->next;
-                       else
-                               requests = cur->next;
-                       break;
-               }
-               prev = cur;
-               cur = cur->next;
-       }
-       ast_mutex_unlock(&peerlock);
+       AST_LIST_LOCK(&peers);
+       AST_LIST_REMOVE(&requests, dr, list);
+       AST_LIST_UNLOCK(&peers);
 }
 
 static int check_request(struct dundi_request *dr)
 {
        struct dundi_request *cur;
-       int res = 0;
-       ast_mutex_lock(&peerlock);
-       cur = requests;
-       while(cur) {
-               if (cur == dr) {
-                       res = 1;
+
+       AST_LIST_LOCK(&peers);
+       AST_LIST_TRAVERSE(&requests, cur, list) {
+               if (cur == dr)
                        break;
-               }
-               cur = cur->next;
        }
-       ast_mutex_unlock(&peerlock);
-       return res;
+       AST_LIST_UNLOCK(&peers);
+       
+       return cur ? 1 : 0;
 }
 
 static unsigned long avoid_crc32(dundi_eid *avoid[])
@@ -3536,8 +3488,8 @@ static int dundi_lookup_internal(struct dundi_result *result, int maxret, struct
        dr.expiration = *expiration;
        dr.cbypass = cbypass;
        dr.crc32 = avoid_crc32(avoid);
-       strncpy(dr.dcontext, dcontext ? dcontext : "e164", sizeof(dr.dcontext) - 1);
-       strncpy(dr.number, number, sizeof(dr.number) - 1);
+       ast_copy_string(dr.dcontext, dcontext ? dcontext : "e164", sizeof(dr.dcontext));
+       ast_copy_string(dr.number, number, sizeof(dr.number));
        if (rooteid)
                dr.root_eid = *rooteid;
        res = register_request(&dr, &pending);
@@ -3546,18 +3498,21 @@ static int dundi_lookup_internal(struct dundi_result *result, int maxret, struct
                if (rooteid && !dundi_eid_cmp(&dr.root_eid, &pending->root_eid)) {
                        /* This is on behalf of someone else.  Go ahead and close this out since
                           they'll get their answer anyway. */
-                       ast_log(LOG_DEBUG, "Oooh, duplicate request for '%s@%s' for '%s'\n",
-                               dr.number,dr.dcontext,dundi_eid_to_str(eid_str, sizeof(eid_str), &dr.root_eid));
+                       if (option_debug)
+                               ast_log(LOG_DEBUG, "Oooh, duplicate request for '%s@%s' for '%s'\n",
+                                       dr.number,dr.dcontext,dundi_eid_to_str(eid_str, sizeof(eid_str), &dr.root_eid));
                        close(dr.pfds[0]);
                        close(dr.pfds[1]);
                        return -2;
                } else {
                        /* Wait for the cache to populate */
-                       ast_log(LOG_DEBUG, "Waiting for similar request for '%s@%s' for '%s'\n",
-                               dr.number,dr.dcontext,dundi_eid_to_str(eid_str, sizeof(eid_str), &pending->root_eid));
-                       gettimeofday(&start, NULL);
-                       while(check_request(pending) && (calc_ms(&start) < ttlms) && (!chan || !chan->_softhangup)) {
+                       if (option_debug)
+                               ast_log(LOG_DEBUG, "Waiting for similar request for '%s@%s' for '%s'\n",
+                                       dr.number,dr.dcontext,dundi_eid_to_str(eid_str, sizeof(eid_str), &pending->root_eid));
+                       start = ast_tvnow();
+                       while(check_request(pending) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms) && (!chan || !chan->_softhangup)) {
                                /* XXX Would be nice to have a way to poll/select here XXX */
+                               /* XXX this is a busy wait loop!!! */
                                usleep(1);
                        }
                        /* Continue on as normal, our cache should kick in */
@@ -3569,12 +3524,12 @@ static int dundi_lookup_internal(struct dundi_result *result, int maxret, struct
                skipped = 0;
                foundcache = 0;
                build_transactions(&dr, ttl, order, &foundcache, &skipped, blockempty, cbypass, modeselect, skip, avoid, direct);
-       } while (skipped && !foundcache && !dr.trans);
+       } while (skipped && !foundcache && AST_LIST_EMPTY(&dr.trans));
        /* If no TTL, abort and return 0 now after setting TTL expired hint.  Couldn't
           do this earlier because we didn't know if we were going to have transactions
           or not. */
        if (!ttl) {
-               hmd->flags |= DUNDI_HINT_TTL_EXPIRED;
+               ast_set_flag_nonstd(hmd, DUNDI_HINT_TTL_EXPIRED);
                abort_request(&dr);
                unregister_request(&dr);
                close(dr.pfds[0]);
@@ -3587,12 +3542,12 @@ static int dundi_lookup_internal(struct dundi_result *result, int maxret, struct
        /* Actually perform transactions */
        discover_transactions(&dr);
        /* Wait for transaction to come back */
-       gettimeofday(&start, NULL);
-       while(dr.trans && (calc_ms(&start) < ttlms) && (!chan || !chan->_softhangup)) {
+       start = ast_tvnow();
+       while (!AST_LIST_EMPTY(&dr.trans) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms) && (!chan || !chan->_softhangup)) {
                ms = 100;
                ast_waitfor_n_fd(dr.pfds, 1, &ms, NULL);
        }
-       if (chan && chan->_softhangup)
+       if (chan && chan->_softhangup && option_debug)
                ast_log(LOG_DEBUG, "Hrm, '%s' hungup before their query for %s@%s finished\n", chan->name, dr.number, dr.dcontext);
        cancel_request(&dr);
        unregister_request(&dr);
@@ -3608,7 +3563,7 @@ int dundi_lookup(struct dundi_result *result, int maxret, struct ast_channel *ch
        struct dundi_hint_metadata hmd;
        dundi_eid *avoid[1] = { NULL, };
        int direct[1] = { 0, };
-       int expiration = DUNDI_DEFAULT_CACHE_TIME;
+       int expiration = dundi_cache_time;
        memset(&hmd, 0, sizeof(hmd));
        hmd.flags = DUNDI_HINT_DONT_ASK | DUNDI_HINT_UNAFFECTED;
        return dundi_lookup_internal(result, maxret, chan, dcontext, number, dundi_ttl, 0, &hmd, &expiration, cbypass, 0, NULL, avoid, direct);
@@ -3617,45 +3572,37 @@ int dundi_lookup(struct dundi_result *result, int maxret, struct ast_channel *ch
 static void reschedule_precache(const char *number, const char *context, int expiration)
 {
        int len;
-       struct dundi_precache_queue *qe, *prev=NULL;
-       ast_mutex_lock(&pclock);
-       qe = pcq;
-       while(qe) {
+       struct dundi_precache_queue *qe, *prev;
+
+       AST_LIST_LOCK(&pcq);
+       AST_LIST_TRAVERSE_SAFE_BEGIN(&pcq, qe, list) {
                if (!strcmp(number, qe->number) && !strcasecmp(context, qe->context)) {
-                       if (prev)
-                               prev->next = qe->next;
-                       else
-                               pcq = qe->next;
-                       qe->next = NULL;
+                       AST_LIST_REMOVE_CURRENT(&pcq, list);
                        break;
                }
-               prev = qe;
-               qe = qe->next;
-       };
+       }
+       AST_LIST_TRAVERSE_SAFE_END
        if (!qe) {
-               len = sizeof(struct dundi_precache_queue);
+               len = sizeof(*qe);
                len += strlen(number) + 1;
                len += strlen(context) + 1;
-               qe = malloc(len);
-               if (qe) {
-                       memset(qe, 0, len);
-                       strcpy(qe->number, number);
-                       qe->context = qe->number + strlen(number) + 1;
-                       strcpy(qe->context, context);
+               if (!(qe = ast_calloc(1, len))) {
+                       AST_LIST_UNLOCK(&pcq);
+                       return;
                }
+               strcpy(qe->number, number);
+               qe->context = qe->number + strlen(number) + 1;
+               strcpy(qe->context, context);
        }
        time(&qe->expiration);
        qe->expiration += expiration;
-       prev = pcq;
-       if (prev) {
-               while(prev->next && (prev->next->expiration <= qe->expiration))
-                       prev = prev->next;
-               qe->next = prev->next;
-               prev->next = qe;
+       if ((prev = AST_LIST_FIRST(&pcq))) {
+               while (AST_LIST_NEXT(prev, list) && ((AST_LIST_NEXT(prev, list))->expiration <= qe->expiration))
+                       prev = AST_LIST_NEXT(prev, list);
+               AST_LIST_INSERT_AFTER(&pcq, prev, qe, list);
        } else
-               pcq = qe;
-       ast_mutex_unlock(&pclock);
-       
+               AST_LIST_INSERT_HEAD(&pcq, qe, list);
+       AST_LIST_UNLOCK(&pcq);
 }
 
 static void dundi_precache_full(void)
@@ -3663,26 +3610,22 @@ static void dundi_precache_full(void)
        struct dundi_mapping *cur;
        struct ast_context *con;
        struct ast_exten *e;
-       cur = mappings;
-       while(cur) {
+
+       AST_LIST_TRAVERSE(&mappings, cur, list) {
                ast_log(LOG_NOTICE, "Should precache context '%s'\n", cur->dcontext);
-               ast_lock_contexts();
-               con = ast_walk_contexts(NULL);
-               while(con) {
-                       if (!strcasecmp(cur->lcontext, ast_get_context_name(con))) {
-                               /* Found the match, now queue them all up */
-                               ast_lock_context(con);
-                               e = ast_walk_context_extensions(con, NULL);
-                               while(e) {
-                                       reschedule_precache(ast_get_extension_name(e), cur->dcontext, 0);
-                                       e = ast_walk_context_extensions(con, e);
-                               }
-                               ast_unlock_context(con);
-                       }
-                       con = ast_walk_contexts(con);
+               ast_rdlock_contexts();
+               con = NULL;
+               while ((con = ast_walk_contexts(con))) {
+                       if (strcasecmp(cur->lcontext, ast_get_context_name(con)))
+                               continue;
+                       /* Found the match, now queue them all up */
+                       ast_rdlock_context(con);
+                       e = NULL;
+                       while ((e = ast_walk_context_extensions(con, e)))
+                               reschedule_precache(ast_get_extension_name(e), cur->dcontext, 0);
+                       ast_unlock_context(con);
                }
                ast_unlock_contexts();
-               cur = cur->next;
        }
 }
 
@@ -3692,35 +3635,31 @@ static int dundi_precache_internal(const char *context, const char *number, int
        struct dundi_hint_metadata hmd;
        struct dundi_result dr2[MAX_RESULTS];
        struct timeval start;
-       struct dundi_mapping *maps=NULL, *cur;
-       int nummaps;
+       struct dundi_mapping *maps = NULL, *cur;
+       int nummaps = 0;
        int foundanswers;
        int foundcache, skipped, ttlms, ms;
        if (!context)
                context = "e164";
-       ast_log(LOG_DEBUG, "Precache internal (%s@%s)!\n", number, context);
+       if (option_debug)
+               ast_log(LOG_DEBUG, "Precache internal (%s@%s)!\n", number, context);
 
-       ast_mutex_lock(&peerlock);
-       nummaps = 0;
-       cur = mappings;
-       while(cur) {
+       AST_LIST_LOCK(&peers);
+       AST_LIST_TRAVERSE(&mappings, cur, list) {
                if (!strcasecmp(cur->dcontext, context))
                        nummaps++;
-               cur = cur->next;
        }
        if (nummaps) {
-               maps = alloca(nummaps * sizeof(struct dundi_mapping));
+               maps = alloca(nummaps * sizeof(*maps));
                nummaps = 0;
                if (maps) {
-                       cur = mappings;
-                       while(cur) {
+                       AST_LIST_TRAVERSE(&mappings, cur, list) {
                                if (!strcasecmp(cur->dcontext, context))
                                        maps[nummaps++] = *cur;
-                               cur = cur->next;
                        }
                }
        }
-       ast_mutex_unlock(&peerlock);
+       AST_LIST_UNLOCK(&peers);
        if (!nummaps || !maps)
                return -1;
        ttlms = DUNDI_FLUFF_TIME + ttl * DUNDI_TTL_TIME;
@@ -3728,10 +3667,10 @@ static int dundi_precache_internal(const char *context, const char *number, int
        memset(&dr, 0, sizeof(dr));
        memset(&hmd, 0, sizeof(hmd));
        dr.dr = dr2;
-       strncpy(dr.number, number, sizeof(dr.number) - 1);
-       strncpy(dr.dcontext, context ? context : "e164", sizeof(dr.dcontext) - 1);
+       ast_copy_string(dr.number, number, sizeof(dr.number));
+       ast_copy_string(dr.dcontext, context ? context : "e164", sizeof(dr.dcontext));
        dr.maxcount = MAX_RESULTS;
-       dr.expiration = DUNDI_DEFAULT_CACHE_TIME;
+       dr.expiration = dundi_cache_time;
        dr.hmd = &hmd;
        dr.pfds[0] = dr.pfds[1] = -1;
        pipe(dr.pfds);
@@ -3745,8 +3684,8 @@ static int dundi_precache_internal(const char *context, const char *number, int
                else
                        ast_log(LOG_NOTICE, "Weird, expiration = %d, but need to precache for %s@%s?!\n", dr.expiration, dr.number, dr.dcontext);
        }
-       gettimeofday(&start, NULL);
-       while(dr.trans && (calc_ms(&start) < ttlms)) {
+       start = ast_tvnow();
+       while (!AST_LIST_EMPTY(&dr.trans) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms)) {
                if (dr.pfds[0] > -1) {
                        ms = 100;
                        ast_waitfor_n_fd(dr.pfds, 1, &ms, NULL);
@@ -3787,7 +3726,7 @@ static int dundi_query_eid_internal(struct dundi_entity_info *dei, const char *d
        dr.hmd = hmd;
        dr.dei = dei;
        dr.pfds[0] = dr.pfds[1] = -1;
-       strncpy(dr.dcontext, dcontext ? dcontext : "e164", sizeof(dr.dcontext) - 1);
+       ast_copy_string(dr.dcontext, dcontext ? dcontext : "e164", sizeof(dr.dcontext));
        memcpy(&dr.query_eid, eid, sizeof(dr.query_eid));
        if (rooteid)
                dr.root_eid = *rooteid;
@@ -3798,7 +3737,7 @@ static int dundi_query_eid_internal(struct dundi_entity_info *dei, const char *d
           do this earlier because we didn't know if we were going to have transactions
           or not. */
        if (!ttl) {
-               hmd->flags |= DUNDI_HINT_TTL_EXPIRED;
+               ast_set_flag_nonstd(hmd, DUNDI_HINT_TTL_EXPIRED);
                return 0;
        }
                
@@ -3807,8 +3746,8 @@ static int dundi_query_eid_internal(struct dundi_entity_info *dei, const char *d
        /* Actually perform transactions */
        query_transactions(&dr);
        /* Wait for transaction to come back */
-       gettimeofday(&start, NULL);
-       while(dr.trans && (calc_ms(&start) < ttlms))
+       start = ast_tvnow();
+       while (!AST_LIST_EMPTY(&dr.trans) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms))
                usleep(1);
        res = dr.respcount;
        return res;
@@ -3822,93 +3761,99 @@ int dundi_query_eid(struct dundi_entity_info *dei, const char *dcontext, dundi_e
        return dundi_query_eid_internal(dei, dcontext, &eid, &hmd, dundi_ttl, 0, avoid);
 }
 
-static int dundi_lookup_exec(struct ast_channel *chan, void *data)
+static int dundifunc_read(struct ast_channel *chan, const char *cmd, char *num, char *buf, size_t len)
 {
-       char *tmp;
-       char *context = NULL;
+       char *context;
        char *opts;
-       int res = 0;
-       int results = 0;
+       int results;
        int x;
        int bypass = 0;
-       struct localuser *u;
+       struct ast_module_user *u;
        struct dundi_result dr[MAX_RESULTS];
 
-       if (!data || !strlen(data)) {
-               ast_log(LOG_WARNING, "DUNDiLookup requires an argument (number)\n");
-               return 0;
+       buf[0] = '\0';
+
+       if (ast_strlen_zero(num)) {
+               ast_log(LOG_WARNING, "DUNDILOOKUP requires an argument (number)\n");
+               return -1;
        }
-       LOCAL_USER_ADD(u);
-       tmp = ast_strdupa(data);
-       if (tmp) {
-               context = strchr(tmp, '|');
-               if (context) {
-                       *context = '\0';
-                       context++;
-                       opts = strchr(context, '|');
-                       if (opts) {
-                               *opts = '\0';
-                               opts++;
-                       }
-               } else
-                       opts = NULL;
-               if (!context || !strlen(context))
-                       context = "e164";
-               if (!opts)
-                       opts = "";
-               
+
+       u = ast_module_user_add(chan);
+
+       context = strchr(num, '|');
+       if (context) {
+               *context++ = '\0';
+               opts = strchr(context, '|');
+               if (opts) {
+                       *opts++ = '\0';
+                       if (strchr(opts, 'b'))
+                               bypass = 1;
+               }
        }
-       results = dundi_lookup(dr, MAX_RESULTS, NULL, context, tmp, bypass);
+
+       if (ast_strlen_zero(context))
+               context = "e164";
+       
+       results = dundi_lookup(dr, MAX_RESULTS, NULL, context, num, bypass);
        if (results > 0) {
-        sort_results(dr, results);
-        for (x=0;x<results;x++) {
-                       if (dr[x].flags & DUNDI_FLAG_EXISTS) {
-                               pbx_builtin_setvar_helper(chan, "DUNDTECH", dr[x].tech);
-                               pbx_builtin_setvar_helper(chan, "DUNDDEST", dr[x].dest);
+               sort_results(dr, results);
+               for (x = 0; x < results; x++) {
+                       if (ast_test_flag(dr + x, DUNDI_FLAG_EXISTS)) {
+                               snprintf(buf, len, "%s/%s", dr[x].tech, dr[x].dest);
                                break;
-            }
-        }
-    } else {
-               if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->cid.cid_num))
-            chan->priority += 100;
+                       }
+               }
        }
-       LOCAL_USER_REMOVE(u);
-       return res;
+
+       ast_module_user_remove(u);
+
+       return 0;
 }
 
+/*! DUNDILOOKUP
+ * \ingroup functions
+*/
+
+static struct ast_custom_function dundi_function = {
+       .name = "DUNDILOOKUP",
+       .synopsis = "Do a DUNDi lookup of a phone number.",
+       .syntax = "DUNDILOOKUP(number[|context[|options]])",
+       .desc = "This will do a DUNDi lookup of the given phone number.\n"
+       "If no context is given, the default will be e164. The result of\n"
+       "this function will the Technology/Resource found in the DUNDi\n"
+       "lookup. If no results were found, the result will be blank.\n"
+       "If the 'b' option is specified, the internal DUNDi cache will\n"
+       "be bypassed.\n",
+       .read = dundifunc_read,
+};
 
 static void mark_peers(void)
 {
        struct dundi_peer *peer;
-       ast_mutex_lock(&peerlock);
-       peer = peers;
-       while(peer) {
+       AST_LIST_LOCK(&peers);
+       AST_LIST_TRAVERSE(&peers, peer, list) {
                peer->dead = 1;
-               peer = peer->next;
        }
-       ast_mutex_unlock(&peerlock);
+       AST_LIST_UNLOCK(&peers);
 }
 
 static void mark_mappings(void)
 {
        struct dundi_mapping *map;
-       ast_mutex_lock(&peerlock);
-       map = mappings;
-       while(map) {
+       
+       AST_LIST_LOCK(&peers);
+       AST_LIST_TRAVERSE(&mappings, map, list) {
                map->dead = 1;
-               map = map->next;
        }
-       ast_mutex_unlock(&peerlock);
+       AST_LIST_UNLOCK(&peers);
 }
 
-static void destroy_permissions(struct permission *p)
+static void destroy_permissions(struct permissionlist *permlist)
 {
-       struct permission *prev;
-       while(p) {
-               prev = p;
-               p = p->next;
-               free(prev);
-       }
+       struct permission *perm;
+
+       while ((perm = AST_LIST_REMOVE_HEAD(permlist, list)))
+               free(perm);
 }
 
 static void destroy_peer(struct dundi_peer *peer)
@@ -3917,12 +3862,10 @@ static void destroy_peer(struct dundi_peer *peer)
                ast_sched_del(sched, peer->registerid);
        if (peer->regtrans)
                destroy_trans(peer->regtrans, 0);
-       if (peer->keypending)
-               destroy_trans(peer->keypending, 0);
        if (peer->qualifyid > -1)
                ast_sched_del(sched, peer->qualifyid);
-       destroy_permissions(peer->permit);
-       destroy_permissions(peer->include);
+       destroy_permissions(&peer->permit);
+       destroy_permissions(&peer->include);
        free(peer);
 }
 
@@ -3933,66 +3876,45 @@ static void destroy_map(struct dundi_mapping *map)
 
 static void prune_peers(void)
 {
-       struct dundi_peer *peer, *prev, *next;
-       ast_mutex_lock(&peerlock);
-       peer = peers;
-       prev = NULL;
-       while(peer) {
-               next = peer->next;
+       struct dundi_peer *peer;
+
+       AST_LIST_LOCK(&peers);
+       AST_LIST_TRAVERSE_SAFE_BEGIN(&peers, peer, list) {
                if (peer->dead) {
-                       if (prev)
-                               prev->next = peer->next;
-                       else
-                               peers = peer->next;
+                       AST_LIST_REMOVE_CURRENT(&peers, list);
                        destroy_peer(peer);
-               } else
-                       prev = peer;
-               peer = next;
+               }
        }
-       ast_mutex_unlock(&peerlock);
+       AST_LIST_TRAVERSE_SAFE_END
+       AST_LIST_UNLOCK(&peers);
 }
 
 static void prune_mappings(void)
 {
-       struct dundi_mapping *map, *prev, *next;
-       ast_mutex_lock(&peerlock);
-       map = mappings;
-       prev = NULL;
-       while(map) {
-               next = map->next;
+       struct dundi_mapping *map;
+
+       AST_LIST_LOCK(&peers);
+       AST_LIST_TRAVERSE_SAFE_BEGIN(&mappings, map, list) {
                if (map->dead) {
-                       if (prev)
-                               prev->next = map->next;
-                       else
-                               mappings = map->next;
+                       AST_LIST_REMOVE_CURRENT(&mappings, list);
                        destroy_map(map);
-               } else
-                       prev = map;
-               map = next;
+               }
        }
-       ast_mutex_unlock(&peerlock);
+       AST_LIST_TRAVERSE_SAFE_END
+       AST_LIST_UNLOCK(&peers);
 }
 
-static struct permission *append_permission(struct permission *p, char *s, int allow)
+static void append_permission(struct permissionlist *permlist, char *s, int allow)
 {
-       struct permission *start;
-       start = p;
-       if (p) {
-               while(p->next)
-                       p = p->next;
-       }
-       if (p) {
-               p->next = malloc(sizeof(struct permission) + strlen(s) + 1);
-               p = p->next;
-       } else {
-               p = malloc(sizeof(struct permission) + strlen(s) + 1);
-       }
-       if (p) {
-               memset(p, 0, sizeof(struct permission));
-               memcpy(p->name, s, strlen(s) + 1);
-               p->allow = allow;
-       }
-       return start ? start : p;
+       struct permission *perm;
+
+       if (!(perm = ast_calloc(1, sizeof(*perm) + strlen(s) + 1)))
+               return;
+
+       strcpy(perm->name, s);
+       perm->allow = allow;
+
+       AST_LIST_INSERT_TAIL(permlist, perm, list);
 }
 
 #define MAX_OPTS 128
@@ -4003,91 +3925,85 @@ static void build_mapping(char *name, char *value)
        struct dundi_mapping *map;
        int x;
        int y;
+
        t = ast_strdupa(value);
-       if (t) {
-               map = mappings;
-               while(map) {
-                       /* Find a double match */
-                       if (!strcasecmp(map->dcontext, name) && 
-                               (!strncasecmp(map->lcontext, value, strlen(map->lcontext)) && 
-                                 (!value[strlen(map->lcontext)] || 
-                                  (value[strlen(map->lcontext)] == ','))))
-                               break;
-                       map = map->next;
+               
+       AST_LIST_TRAVERSE(&mappings, map, list) {
+               /* Find a double match */
+               if (!strcasecmp(map->dcontext, name) && 
+                       (!strncasecmp(map->lcontext, value, strlen(map->lcontext)) && 
+                         (!value[strlen(map->lcontext)] || 
+                          (value[strlen(map->lcontext)] == ','))))
+                       break;
+       }
+       if (!map) {
+               if (!(map = ast_calloc(1, sizeof(*map))))
+                       return;
+               AST_LIST_INSERT_HEAD(&mappings, map, list);
+               map->dead = 1;
+       }
+       map->options = 0;
+       memset(fields, 0, sizeof(fields));
+       x = 0;
+       while (t && x < MAX_OPTS) {
+               fields[x++] = t;
+               t = strchr(t, ',');
+               if (t) {
+                       *t = '\0';
+                       t++;
                }
-               if (!map) {
-                       map = malloc(sizeof(struct dundi_mapping));
-                       if (map) {
-                               memset(map, 0, sizeof(struct dundi_mapping));
-                               map->next = mappings;
-                               mappings = map;
-                               map->dead = 1;
+       } /* Russell was here, arrrr! */
+       if ((x == 1) && ast_strlen_zero(fields[0])) {
+               /* Placeholder mapping */
+               ast_copy_string(map->dcontext, name, sizeof(map->dcontext));
+               map->dead = 0;
+       } else if (x >= 4) {
+               ast_copy_string(map->dcontext, name, sizeof(map->dcontext));
+               ast_copy_string(map->lcontext, fields[0], sizeof(map->lcontext));
+               if ((sscanf(fields[1], "%d", &map->weight) == 1) && (map->weight >= 0) && (map->weight < 60000)) {
+                       ast_copy_string(map->dest, fields[3], sizeof(map->dest));
+                       if ((map->tech = str2tech(fields[2]))) {
+                               map->dead = 0;
                        }
+               } else {
+                       ast_log(LOG_WARNING, "Invalid weight '%s' specified, deleting entry '%s/%s'\n", fields[1], map->dcontext, map->lcontext);
                }
-               if (map) {
-                       map->options = 0;
-                       memset(fields, 0, sizeof(fields));
-                       x = 0;
-                       while(t && x < MAX_OPTS) {
-                               fields[x++] = t;
-                               t = strchr(t, ',');
-                               if (t) {
-                                       *t = '\0';
-                                       t++;
-                               }
-                       } /* Russell was here, arrrr! */
-                       if ((x == 1) && ast_strlen_zero(fields[0])) {
-                               /* Placeholder mapping */
-                               strncpy(map->dcontext, name, sizeof(map->dcontext) - 1);
-                               map->dead = 0;
-                       } else if (x >= 4) {
-                               strncpy(map->dcontext, name, sizeof(map->dcontext) - 1);
-                               strncpy(map->lcontext, fields[0], sizeof(map->lcontext) - 1);
-                               if ((sscanf(fields[1], "%i", &map->weight) == 1) && (map->weight >= 0) && (map->weight < 60000)) {
-                                       strncpy(map->dest, fields[3], sizeof(map->dest) - 1);
-                                       if ((map->tech = str2tech(fields[2]))) {
-                                               map->dead = 0;
-                                       }
-                               } else {
-                                       ast_log(LOG_WARNING, "Invalid weight '%s' specified, deleting entry '%s/%s'\n", fields[1], map->dcontext, map->lcontext);
-                               }
-                               for (y=4;y<x;y++) {
-                                       if (!strcasecmp(fields[y], "nounsolicited"))
-                                               map->options |= DUNDI_FLAG_NOUNSOLICITED;
-                                       else if (!strcasecmp(fields[y], "nocomunsolicit"))
-                                               map->options |= DUNDI_FLAG_NOCOMUNSOLICIT;
-                                       else if (!strcasecmp(fields[y], "residential"))
-                                               map->options |= DUNDI_FLAG_RESIDENTIAL;
-                                       else if (!strcasecmp(fields[y], "commercial"))
-                                               map->options |= DUNDI_FLAG_COMMERCIAL;
-                                       else if (!strcasecmp(fields[y], "mobile"))
-                                               map->options |= DUNDI_FLAG_MOBILE;
-                                       else if (!strcasecmp(fields[y], "nopartial"))
-                                               map->options |= DUNDI_FLAG_INTERNAL_NOPARTIAL;
-                                       else
-                                               ast_log(LOG_WARNING, "Don't know anything about option '%s'\n", fields[y]);
-                               }
-                       } else 
-                               ast_log(LOG_WARNING, "Expected at least %d arguments in map, but got only %d\n", 4, x);
+               for (y = 4;y < x; y++) {
+                       if (!strcasecmp(fields[y], "nounsolicited"))
+                               map->options |= DUNDI_FLAG_NOUNSOLICITED;
+                       else if (!strcasecmp(fields[y], "nocomunsolicit"))
+                               map->options |= DUNDI_FLAG_NOCOMUNSOLICIT;
+                       else if (!strcasecmp(fields[y], "residential"))
+                               map->options |= DUNDI_FLAG_RESIDENTIAL;
+                       else if (!strcasecmp(fields[y], "commercial"))
+                               map->options |= DUNDI_FLAG_COMMERCIAL;
+                       else if (!strcasecmp(fields[y], "mobile"))
+                               map->options |= DUNDI_FLAG_MOBILE;
+                       else if (!strcasecmp(fields[y], "nopartial"))
+                               map->options |= DUNDI_FLAG_INTERNAL_NOPARTIAL;
+                       else
+                               ast_log(LOG_WARNING, "Don't know anything about option '%s'\n", fields[y]);
                }
-       }
+       } else 
+               ast_log(LOG_WARNING, "Expected at least %d arguments in map, but got only %d\n", 4, x);
 }
 
+/* \note Called with the peers list already locked */
 static int do_register(void *data)
 {
        struct dundi_ie_data ied;
        struct dundi_peer *peer = data;
        char eid_str[20];
        char eid_str2[20];
-       /* Called with peerlock already held */
-       ast_log(LOG_DEBUG, "Register us as '%s' to '%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->us_eid), dundi_eid_to_str(eid_str2, sizeof(eid_str2), &peer->eid));
+       if (option_debug)
+               ast_log(LOG_DEBUG, "Register us as '%s' to '%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->us_eid), dundi_eid_to_str(eid_str2, sizeof(eid_str2), &peer->eid));
        peer->registerid = ast_sched_add(sched, default_expiration * 1000, do_register, data);
        /* Destroy old transaction if there is one */
        if (peer->regtrans)
                destroy_trans(peer->regtrans, 0);
        peer->regtrans = create_transaction(peer);
        if (peer->regtrans) {
-               peer->regtrans->flags |= FLAG_ISREG;
+               ast_set_flag(peer->regtrans, FLAG_ISREG);
                memset(&ied, 0, sizeof(ied));
                dundi_ie_append_short(&ied, DUNDI_IE_VERSION, DUNDI_DEFAULT_VERSION);
                dundi_ie_append_eid(&ied, DUNDI_IE_EID, &peer->regtrans->us_eid);
@@ -4128,8 +4044,8 @@ static void qualify_peer(struct dundi_peer *peer, int schedonly)
                if (!schedonly)
                        peer->qualtrans = create_transaction(peer);
                if (peer->qualtrans) {
-                       gettimeofday(&peer->qualtx, NULL);
-                       peer->qualtrans->flags |= FLAG_ISQUAL;
+                       peer->qualtx = ast_tvnow();
+                       ast_set_flag(peer->qualtrans, FLAG_ISQUAL);
                        dundi_send(peer->qualtrans, DUNDI_COMMAND_NULL, 0, 1, NULL);
                }
        }
@@ -4167,151 +4083,143 @@ static void build_peer(dundi_eid *eid, struct ast_variable *v, int *globalpcmode
        int needregister=0;
        char eid_str[20];
 
-       ast_mutex_lock(&peerlock);
-       peer = peers;
-       while(peer) {
+       AST_LIST_LOCK(&peers);
+       AST_LIST_TRAVERSE(&peers, peer, list) {
                if (!dundi_eid_cmp(&peer->eid, eid)) {  
                        break;
                }
-               peer = peer->next;
        }
        if (!peer) {
                /* Add us into the list */
-               peer = malloc(sizeof(struct dundi_peer));
-               if (peer) {
-                       memset(peer, 0, sizeof(struct dundi_peer));
-                       peer->registerid = -1;
-                       peer->registerexpire = -1;
-                       peer->qualifyid = -1;
-                       peer->addr.sin_family = AF_INET;
-                       peer->addr.sin_port = htons(DUNDI_PORT);
-                       populate_addr(peer, eid);
-                       peer->next = peers;
-                       peers = peer;
+               if (!(peer = ast_calloc(1, sizeof(*peer)))) {
+                       AST_LIST_UNLOCK(&peers);
+                       return;
                }
-       }
-       if (peer) {
-               peer->dead = 0;
-               peer->eid = *eid;
-               peer->us_eid = global_eid;
-               destroy_permissions(peer->permit);
-               destroy_permissions(peer->include);
-               peer->permit = NULL;
-               peer->include = NULL;
-               if (peer->registerid > -1)
-                       ast_sched_del(sched, peer->registerid);
                peer->registerid = -1;
-               while(v) {
-                       if (!strcasecmp(v->name, "inkey")) {
-                               strncpy(peer->inkey, v->value, sizeof(peer->inkey) - 1);
-                       } else if (!strcasecmp(v->name, "outkey")) {
-                               strncpy(peer->outkey, v->value, sizeof(peer->outkey) - 1);
-                       } else if (!strcasecmp(v->name, "host")) {
-                               if (!strcasecmp(v->value, "dynamic")) {
-                                       peer->dynamic = 1;
+               peer->registerexpire = -1;
+               peer->qualifyid = -1;
+               peer->addr.sin_family = AF_INET;
+               peer->addr.sin_port = htons(DUNDI_PORT);
+               populate_addr(peer, eid);
+               AST_LIST_INSERT_HEAD(&peers, peer, list);
+       }
+       peer->dead = 0;
+       peer->eid = *eid;
+       peer->us_eid = global_eid;
+       destroy_permissions(&peer->permit);
+       destroy_permissions(&peer->include);
+       if (peer->registerid > -1)
+               ast_sched_del(sched, peer->registerid);
+       peer->registerid = -1;
+       for (; v; v = v->next) {
+               if (!strcasecmp(v->name, "inkey")) {
+                       ast_copy_string(peer->inkey, v->value, sizeof(peer->inkey));
+               } else if (!strcasecmp(v->name, "outkey")) {
+                       ast_copy_string(peer->outkey, v->value, sizeof(peer->outkey));
+               } else if (!strcasecmp(v->name, "host")) {
+                       if (!strcasecmp(v->value, "dynamic")) {
+                               peer->dynamic = 1;
+                       } else {
+                               hp = ast_gethostbyname(v->value, &he);
+                               if (hp) {
+                                       memcpy(&peer->addr.sin_addr, hp->h_addr, sizeof(peer->addr.sin_addr));
+                                       peer->dynamic = 0;
                                } else {
-                                       hp = ast_gethostbyname(v->value, &he);
-                                       if (hp) {
-                                               memcpy(&peer->addr.sin_addr, hp->h_addr, sizeof(peer->addr.sin_addr));
-                                               peer->dynamic = 0;
-                                       } else {
-                                               ast_log(LOG_WARNING, "Unable to find host '%s' at line %d\n", v->value, v->lineno);
-                                               peer->dead = 1;
-                                       }
-                               }
-                       } else if (!strcasecmp(v->name, "ustothem")) {
-                               if (!dundi_str_to_eid(&testeid, v->value))
-                                       peer->us_eid = testeid;
-                               else
-                                       ast_log(LOG_WARNING, "'%s' is not a valid DUNDi Entity Identifier at line %d\n", v->value, v->lineno);
-                       } else if (!strcasecmp(v->name, "include")) {
-                               peer->include = append_permission(peer->include, v->value, 1);
-                       } else if (!strcasecmp(v->name, "permit")) {
-                               peer->permit = append_permission(peer->permit, v->value, 1);
-                       } else if (!strcasecmp(v->name, "noinclude")) {
-                               peer->include = append_permission(peer->include, v->value, 0);
-                       } else if (!strcasecmp(v->name, "deny")) {
-                               peer->permit = append_permission(peer->permit, v->value, 0);
-                       } else if (!strcasecmp(v->name, "register")) {
-                               needregister = ast_true(v->value);
-                       } else if (!strcasecmp(v->name, "order")) {
-                               if (!strcasecmp(v->value, "primary"))
-                                       peer->order = 0;
-                               else if (!strcasecmp(v->value, "secondary"))
-                                       peer->order = 1;
-                               else if (!strcasecmp(v->value, "tertiary"))
-                                       peer->order = 2;
-                               else if (!strcasecmp(v->value, "quartiary"))
-                                       peer->order = 3;
-                               else {
-                                       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);
-                               }
-                       } else if (!strcasecmp(v->name, "qualify")) {
-                               if (!strcasecmp(v->value, "no")) {
-                                       peer->maxms = 0;
-                               } else if (!strcasecmp(v->value, "yes")) {
-                                       peer->maxms = DEFAULT_MAXMS;
-                               } else if (sscanf(v->value, "%d", &peer->maxms) != 1) {
-                                       ast_log(LOG_WARNING, "Qualification of peer '%s' should be 'yes', 'no', or a number of milliseconds at line %d of dundi.conf\n", 
-                                               dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), v->lineno);
-                                       peer->maxms = 0;
-                               }
-                       } else if (!strcasecmp(v->name, "model")) {
-                               if (!strcasecmp(v->value, "inbound"))
-                                       peer->model = DUNDI_MODEL_INBOUND;
-                               else if (!strcasecmp(v->value, "outbound")) 
-                                       peer->model = DUNDI_MODEL_OUTBOUND;
-                               else if (!strcasecmp(v->value, "symmetric"))
-                                       peer->model = DUNDI_MODEL_SYMMETRIC;
-                               else if (!strcasecmp(v->value, "none"))
-                                       peer->model = 0;
-                               else {
-                                       ast_log(LOG_WARNING, "Unknown model '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n", 
-                                               v->value, v->lineno);
-                               }
-                       } else if (!strcasecmp(v->name, "precache")) {
-                               if (!strcasecmp(v->value, "inbound"))
-                                       peer->pcmodel = DUNDI_MODEL_INBOUND;
-                               else if (!strcasecmp(v->value, "outbound")) 
-                                       peer->pcmodel = DUNDI_MODEL_OUTBOUND;
-                               else if (!strcasecmp(v->value, "symmetric"))
-                                       peer->pcmodel = DUNDI_MODEL_SYMMETRIC;
-                               else if (!strcasecmp(v->value, "none"))
-                                       peer->pcmodel = 0;
-                               else {
-                                       ast_log(LOG_WARNING, "Unknown pcmodel '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n", 
-                                               v->value, v->lineno);
+                                       ast_log(LOG_WARNING, "Unable to find host '%s' at line %d\n", v->value, v->lineno);
+                                       peer->dead = 1;
                                }
                        }
-                       v = v->next;
-               }
-               (*globalpcmode) |= peer->pcmodel;
-               if (!peer->model && !peer->pcmodel) {
-                       ast_log(LOG_WARNING, "Peer '%s' lacks a model or pcmodel, discarding!\n", 
-                               dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
-                       peer->dead = 1;
-               } else if ((peer->model & DUNDI_MODEL_INBOUND) && (peer->pcmodel & DUNDI_MODEL_OUTBOUND)) {
-                       ast_log(LOG_WARNING, "Peer '%s' may not be both inbound/symmetric model and outbound/symmetric precache model, discarding!\n", 
-                               dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
-                       peer->dead = 1;
-               } else if ((peer->model & DUNDI_MODEL_OUTBOUND) && (peer->pcmodel & DUNDI_MODEL_INBOUND)) {
-                       ast_log(LOG_WARNING, "Peer '%s' may not be both outbound/symmetric model and inbound/symmetric precache model, discarding!\n", 
-                               dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
-                       peer->dead = 1;
-               } else if (peer->include && !(peer->model & DUNDI_MODEL_OUTBOUND) && !(peer->pcmodel & DUNDI_MODEL_INBOUND)) {
-                       ast_log(LOG_WARNING, "Peer '%s' is supposed to be included in outbound searches but isn't an outbound peer or inbound precache!\n", 
-                               dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
-               } else if (peer->permit && !(peer->model & DUNDI_MODEL_INBOUND) && !(peer->pcmodel & DUNDI_MODEL_OUTBOUND)) {
-                       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", 
-                               dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
-               } else { 
-                       if (needregister) {
-                               peer->registerid = ast_sched_add(sched, 2000, do_register, peer);
+               } else if (!strcasecmp(v->name, "ustothem")) {
+                       if (!dundi_str_to_eid(&testeid, v->value))
+                               peer->us_eid = testeid;
+                       else
+                               ast_log(LOG_WARNING, "'%s' is not a valid DUNDi Entity Identifier at line %d\n", v->value, v->lineno);
+               } else if (!strcasecmp(v->name, "include")) {
+                       append_permission(&peer->include, v->value, 1);
+               } else if (!strcasecmp(v->name, "permit")) {
+                       append_permission(&peer->permit, v->value, 1);
+               } else if (!strcasecmp(v->name, "noinclude")) {
+                       append_permission(&peer->include, v->value, 0);
+               } else if (!strcasecmp(v->name, "deny")) {
+                       append_permission(&peer->permit, v->value, 0);
+               } else if (!strcasecmp(v->name, "register")) {
+                       needregister = ast_true(v->value);
+               } else if (!strcasecmp(v->name, "order")) {
+                       if (!strcasecmp(v->value, "primary"))
+                               peer->order = 0;
+                       else if (!strcasecmp(v->value, "secondary"))
+                               peer->order = 1;
+                       else if (!strcasecmp(v->value, "tertiary"))
+                               peer->order = 2;
+                       else if (!strcasecmp(v->value, "quartiary"))
+                               peer->order = 3;
+                       else {
+                               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);
+                       }
+               } else if (!strcasecmp(v->name, "qualify")) {
+                       if (!strcasecmp(v->value, "no")) {
+                               peer->maxms = 0;
+                       } else if (!strcasecmp(v->value, "yes")) {
+                               peer->maxms = DEFAULT_MAXMS;
+                       } else if (sscanf(v->value, "%d", &peer->maxms) != 1) {
+                               ast_log(LOG_WARNING, "Qualification of peer '%s' should be 'yes', 'no', or a number of milliseconds at line %d of dundi.conf\n", 
+                                       dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), v->lineno);
+                               peer->maxms = 0;
+                       }
+               } else if (!strcasecmp(v->name, "model")) {
+                       if (!strcasecmp(v->value, "inbound"))
+                               peer->model = DUNDI_MODEL_INBOUND;
+                       else if (!strcasecmp(v->value, "outbound")) 
+                               peer->model = DUNDI_MODEL_OUTBOUND;
+                       else if (!strcasecmp(v->value, "symmetric"))
+                               peer->model = DUNDI_MODEL_SYMMETRIC;
+                       else if (!strcasecmp(v->value, "none"))
+                               peer->model = 0;
+                       else {
+                               ast_log(LOG_WARNING, "Unknown model '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n", 
+                                       v->value, v->lineno);
+                       }
+               } else if (!strcasecmp(v->name, "precache")) {
+                       if (!strcasecmp(v->value, "inbound"))
+                               peer->pcmodel = DUNDI_MODEL_INBOUND;
+                       else if (!strcasecmp(v->value, "outbound")) 
+                               peer->pcmodel = DUNDI_MODEL_OUTBOUND;
+                       else if (!strcasecmp(v->value, "symmetric"))
+                               peer->pcmodel = DUNDI_MODEL_SYMMETRIC;
+                       else if (!strcasecmp(v->value, "none"))
+                               peer->pcmodel = 0;
+                       else {
+                               ast_log(LOG_WARNING, "Unknown pcmodel '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n", 
+                                       v->value, v->lineno);
                        }
-                       qualify_peer(peer, 1);
                }
        }
-       ast_mutex_unlock(&peerlock);
+       (*globalpcmode) |= peer->pcmodel;
+       if (!peer->model && !peer->pcmodel) {
+               ast_log(LOG_WARNING, "Peer '%s' lacks a model or pcmodel, discarding!\n", 
+                       dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
+               peer->dead = 1;
+       } else if ((peer->model & DUNDI_MODEL_INBOUND) && (peer->pcmodel & DUNDI_MODEL_OUTBOUND)) {
+               ast_log(LOG_WARNING, "Peer '%s' may not be both inbound/symmetric model and outbound/symmetric precache model, discarding!\n", 
+                       dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
+               peer->dead = 1;
+       } else if ((peer->model & DUNDI_MODEL_OUTBOUND) && (peer->pcmodel & DUNDI_MODEL_INBOUND)) {
+               ast_log(LOG_WARNING, "Peer '%s' may not be both outbound/symmetric model and inbound/symmetric precache model, discarding!\n", 
+                       dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
+               peer->dead = 1;
+       } else if (!AST_LIST_EMPTY(&peer->include) && !(peer->model & DUNDI_MODEL_OUTBOUND) && !(peer->pcmodel & DUNDI_MODEL_INBOUND)) {
+               ast_log(LOG_WARNING, "Peer '%s' is supposed to be included in outbound searches but isn't an outbound peer or inbound precache!\n", 
+                       dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
+       } else if (!AST_LIST_EMPTY(&peer->permit) && !(peer->model & DUNDI_MODEL_INBOUND) && !(peer->pcmodel & DUNDI_MODEL_OUTBOUND)) {
+               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", 
+                       dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
+       } else { 
+               if (needregister) {
+                       peer->registerid = ast_sched_add(sched, 2000, do_register, peer);
+               }
+               qualify_peer(peer, 1);
+       }
+       AST_LIST_UNLOCK(&peers);
 }
 
 static int dundi_helper(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *data, int flag)
@@ -4328,24 +4236,24 @@ static int dundi_helper(struct ast_channel *chan, const char *context, const cha
                /* If done as a macro, use macro extension */
                if (!strcasecmp(exten, "s")) {
                        exten = pbx_builtin_getvar_helper(chan, "ARG1");
-                       if (!exten || ast_strlen_zero(exten))
+                       if (ast_strlen_zero(exten))
                                exten = chan->macroexten;
-                       if (!exten || ast_strlen_zero(exten))
+                       if (ast_strlen_zero(exten))
                                exten = chan->exten;
-                       if (!exten || ast_strlen_zero(exten)) { 
+                       if (ast_strlen_zero(exten)) {   
                                ast_log(LOG_WARNING, "Called in Macro mode with no ARG1 or MACRO_EXTEN?\n");
                                return -1;
                        }
                }
-               if (!data || ast_strlen_zero(data))
+               if (ast_strlen_zero(data))
                        data = "e164";
        } else {
-               if (!data || ast_strlen_zero(data))
+               if (ast_strlen_zero(data))
                        data = context;
        }
        res = dundi_lookup(results, MAX_RESULTS, chan, data, exten, 0);
        for (x=0;x<res;x++) {
-               if (results[x].flags & flag)
+               if (ast_test_flag(results + x, flag))
                        found++;
        }
        if (found >= priority)
@@ -4363,12 +4271,13 @@ static int dundi_canmatch(struct ast_channel *chan, const char *context, const c
        return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_CANMATCH);
 }
 
-static int dundi_exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, int newstack, 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)
 {
        struct dundi_result results[MAX_RESULTS];
        int res;
        int x=0;
        char req[1024];
+       const char *dundiargs;
        struct ast_app *dial;
        
        if (!strncasecmp(context, "macro-", 6)) {
@@ -4379,26 +4288,26 @@ static int dundi_exec(struct ast_channel *chan, const char *context, const char
                /* If done as a macro, use macro extension */
                if (!strcasecmp(exten, "s")) {
                        exten = pbx_builtin_getvar_helper(chan, "ARG1");
-                       if (!exten || ast_strlen_zero(exten))
+                       if (ast_strlen_zero(exten))
                                exten = chan->macroexten;
-                       if (!exten || ast_strlen_zero(exten))
+                       if (ast_strlen_zero(exten))
                                exten = chan->exten;
-                       if (!exten || ast_strlen_zero(exten)) { 
+                       if (ast_strlen_zero(exten)) {   
                                ast_log(LOG_WARNING, "Called in Macro mode with no ARG1 or MACRO_EXTEN?\n");
                                return -1;
                        }
                }
-               if (!data || ast_strlen_zero(data))
+               if (ast_strlen_zero(data))
                        data = "e164";
        } else {
-               if (!data || ast_strlen_zero(data))
+               if (ast_strlen_zero(data))
                        data = context;
        }
        res = dundi_lookup(results, MAX_RESULTS, chan, data, exten, 0);
        if (res > 0) {
                sort_results(results, res);
                for (x=0;x<res;x++) {
-                       if (results[x].flags & DUNDI_FLAG_EXISTS) {
+                       if (ast_test_flag(results + x, DUNDI_FLAG_EXISTS)) {
                                if (!--priority)
                                        break;
                        }
@@ -4406,10 +4315,12 @@ static int dundi_exec(struct ast_channel *chan, const char *context, const char
        }
        if (x < res) {
                /* Got a hit! */
-               snprintf(req, sizeof(req), "%s/%s", results[x].tech, results[x].dest);
+               dundiargs = pbx_builtin_getvar_helper(chan, "DUNDIDIALARGS");
+               snprintf(req, sizeof(req), "%s/%s||%s", results[x].tech, results[x].dest, 
+                       S_OR(dundiargs, ""));
                dial = pbx_findapp("Dial");
                if (dial)
-                       res = pbx_exec(chan, dial, req, newstack);
+                       res = pbx_exec(chan, dial, req);
        } else
                res = -1;
        return res;
@@ -4437,7 +4348,7 @@ static int set_config(char *config_file, struct sockaddr_in* sin)
        char *cat;
        int format;
        int x;
-       char hn[256];
+       char hn[MAXHOSTNAMELEN] = "";
        struct ast_hostent he;
        struct hostent *hp;
        struct sockaddr_in sin2;
@@ -4446,7 +4357,8 @@ static int set_config(char *config_file, struct sockaddr_in* sin)
        dundi_eid testeid;
 
        dundi_ttl = DUNDI_DEFAULT_TTL;
-       cfg = ast_load(config_file);
+       dundi_cache_time = DUNDI_DEFAULT_CACHE_TIME;
+       cfg = ast_config_load(config_file);
        
        
        if (!cfg) {
@@ -4454,19 +4366,19 @@ static int set_config(char *config_file, struct sockaddr_in* sin)
                return -1;
        }
        ipaddr[0] = '\0';
-       if (!gethostname(hn, sizeof(hn))) {
+       if (!gethostname(hn, sizeof(hn)-1)) {
                hp = ast_gethostbyname(hn, &he);
                if (hp) {
                        memcpy(&sin2.sin_addr, hp->h_addr, sizeof(sin2.sin_addr));
-                       ast_inet_ntoa(ipaddr, sizeof(ipaddr), sin2.sin_addr);
+                       ast_copy_string(ipaddr, ast_inet_ntoa(sin2.sin_addr), sizeof(ipaddr));
                } else
                        ast_log(LOG_WARNING, "Unable to look up host '%s'\n", hn);
        } else
                ast_log(LOG_WARNING, "Unable to get host name!\n");
-       ast_mutex_lock(&peerlock);
+       AST_LIST_LOCK(&peers);
        reset_global_eid();
        global_storehistory = 0;
-       strncpy(secretpath, "dundi", sizeof(secretpath) - 1);
+       ast_copy_string(secretpath, "dundi", sizeof(secretpath));
        v = ast_variable_browse(cfg, "general");
        while(v) {
                if (!strcasecmp(v->name, "port")){ 
@@ -4486,14 +4398,14 @@ static int set_config(char *config_file, struct sockaddr_in* sin)
                } else if (!strcasecmp(v->name, "authdebug")) {
                        authdebug = ast_true(v->value);
                } else if (!strcasecmp(v->name, "ttl")) {
-                       if ((sscanf(v->value, "%i", &x) == 1) && (x > 0) && (x < DUNDI_DEFAULT_TTL)) {
+                       if ((sscanf(v->value, "%d", &x) == 1) && (x > 0) && (x < DUNDI_DEFAULT_TTL)) {
                                dundi_ttl = x;
                        } else {
                                ast_log(LOG_WARNING, "'%s' is not a valid TTL at line %d, must be number from 1 to %d\n",
                                        v->value, v->lineno, DUNDI_DEFAULT_TTL);
                        }
                } else if (!strcasecmp(v->name, "autokill")) {
-                       if (sscanf(v->value, "%i", &x) == 1) {
+                       if (sscanf(v->value, "%d", &x) == 1) {
                                if (x >= 0)
                                        global_autokilltimeout = x;
                                else
@@ -4509,7 +4421,7 @@ static int set_config(char *config_file, struct sockaddr_in* sin)
                        else
                                ast_log(LOG_WARNING, "Invalid global endpoint identifier '%s' at line %d\n", v->value, v->lineno);
                } else if (!strcasecmp(v->name, "tos")) {
-                       if (sscanf(v->value, "%i", &format) == 1)
+                       if (sscanf(v->value, "%d", &format) == 1)
                                tos = format & 0xff;
                        else if (!strcasecmp(v->value, "lowdelay"))
                                tos = IPTOS_LOWDELAY;
@@ -4517,38 +4429,45 @@ static int set_config(char *config_file, struct sockaddr_in* sin)
                                tos = IPTOS_THROUGHPUT;
                        else if (!strcasecmp(v->value, "reliability"))
                                tos = IPTOS_RELIABILITY;
-#if !defined(__NetBSD__) && !defined(SOLARIS)
+#if !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(SOLARIS)
                        else if (!strcasecmp(v->value, "mincost"))
                                tos = IPTOS_MINCOST;
 #endif
                        else if (!strcasecmp(v->value, "none"))
                                tos = 0;
                        else
-#if defined(__NetBSD__) && !defined(SOLARIS)
+#if !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(SOLARIS)
                                ast_log(LOG_WARNING, "Invalid tos value at line %d, should be 'lowdelay', 'throughput', 'reliability', 'mincost', or 'none'\n", v->lineno);
 #else
                                ast_log(LOG_WARNING, "Invalid tos value at line %d, should be 'lowdelay', 'throughput', 'reliability', or 'none'\n", v->lineno);
 #endif
                } else if (!strcasecmp(v->name, "department")) {
-                       strncpy(dept, v->value, sizeof(dept) - 1);
+                       ast_copy_string(dept, v->value, sizeof(dept));
                } else if (!strcasecmp(v->name, "organization")) {
-                       strncpy(org, v->value, sizeof(org) - 1);
+                       ast_copy_string(org, v->value, sizeof(org));
                } else if (!strcasecmp(v->name, "locality")) {
-                       strncpy(locality, v->value, sizeof(locality) - 1);
+                       ast_copy_string(locality, v->value, sizeof(locality));
                } else if (!strcasecmp(v->name, "stateprov")) {
-                       strncpy(stateprov, v->value, sizeof(stateprov) - 1);
+                       ast_copy_string(stateprov, v->value, sizeof(stateprov));
                } else if (!strcasecmp(v->name, "country")) {
-                       strncpy(country, v->value, sizeof(country) - 1);
+                       ast_copy_string(country, v->value, sizeof(country));
                } else if (!strcasecmp(v->name, "email")) {
-                       strncpy(email, v->value, sizeof(email) - 1);
+                       ast_copy_string(email, v->value, sizeof(email));
                } else if (!strcasecmp(v->name, "phone")) {
-                       strncpy(phone, v->value, sizeof(phone) - 1);
+                       ast_copy_string(phone, v->value, sizeof(phone));
                } else if (!strcasecmp(v->name, "storehistory")) {
                        global_storehistory = ast_true(v->value);
+               } else if (!strcasecmp(v->name, "cachetime")) {
+                       if ((sscanf(v->value, "%d", &x) == 1)) {
+                               dundi_cache_time = x;
+                       } else {
+                               ast_log(LOG_WARNING, "'%s' is not a valid cache time at line %d. Using default value '%d'.\n",
+                                       v->value, v->lineno, DUNDI_DEFAULT_CACHE_TIME);
+                       }
                }
                v = v->next;
        }
-       ast_mutex_unlock(&peerlock);
+       AST_LIST_UNLOCK(&peers);
        mark_mappings();
        v = ast_variable_browse(cfg, "mappings");
        while(v) {
@@ -4569,56 +4488,42 @@ static int set_config(char *config_file, struct sockaddr_in* sin)
                cat = ast_category_browse(cfg, cat);
        }
        prune_peers();
-       ast_destroy(cfg);
+       ast_config_destroy(cfg);
        load_password();
        if (globalpcmodel & DUNDI_MODEL_OUTBOUND)
                dundi_precache_full();
        return 0;
 }
 
-int unload_module(void)
+static int unload_module(void)
 {
-       int res;
-       STANDARD_HANGUP_LOCALUSERS;
-       ast_cli_unregister(&cli_debug);
-       ast_cli_unregister(&cli_store_history);
-       ast_cli_unregister(&cli_flush);
-       ast_cli_unregister(&cli_no_debug);
-       ast_cli_unregister(&cli_no_store_history);
-       ast_cli_unregister(&cli_show_peers);
-       ast_cli_unregister(&cli_show_entityid);
-       ast_cli_unregister(&cli_show_trans);
-       ast_cli_unregister(&cli_show_requests);
-       ast_cli_unregister(&cli_show_mappings);
-       ast_cli_unregister(&cli_show_precache);
-       ast_cli_unregister(&cli_show_peer);
-       ast_cli_unregister(&cli_lookup);
-       ast_cli_unregister(&cli_precache);
-       ast_cli_unregister(&cli_queryeid);
+       ast_module_user_hangup_all();
+
+       ast_cli_unregister_multiple(cli_dundi, sizeof(cli_dundi) / sizeof(struct ast_cli_entry));
        ast_unregister_switch(&dundi_switch);
-       res = ast_unregister_application(app);
-       return res;
+       ast_custom_function_unregister(&dundi_function);
+       sched_context_destroy(sched);
+
+       return 0;
 }
 
-int reload(void)
+static int reload(void)
 {
        struct sockaddr_in sin;
-       set_config("dundi.conf",&sin);
+
+       if (set_config("dundi.conf", &sin))
+               return -1;
+
        return 0;
 }
 
-int load_module(void)
+static int load_module(void)
 {
-       int res=0;
        struct sockaddr_in sin;
-       char iabuf[INET_ADDRSTRLEN];
-       
+
        dundi_set_output(dundi_debug_output);
        dundi_set_error(dundi_error_output);
        
-       /* Seed random number generator */
-       srand(time(NULL));
-       
        sin.sin_family = AF_INET;
        sin.sin_port = ntohs(DUNDI_PORT);
        sin.sin_addr.s_addr = INADDR_ANY;
@@ -4627,40 +4532,22 @@ int load_module(void)
        io = io_context_create();
        sched = sched_context_create();
        
-       if (!io || !sched) {
-               ast_log(LOG_ERROR, "Out of memory\n");
-               return -1;
-       }
+       if (!io || !sched)
+               return AST_MODULE_LOAD_FAILURE;
 
-       ast_cli_register(&cli_debug);
-       ast_cli_register(&cli_store_history);
-       ast_cli_register(&cli_flush);
-       ast_cli_register(&cli_no_debug);
-       ast_cli_register(&cli_no_store_history);
-       ast_cli_register(&cli_show_peers);
-       ast_cli_register(&cli_show_entityid);
-       ast_cli_register(&cli_show_trans);
-       ast_cli_register(&cli_show_requests);
-       ast_cli_register(&cli_show_mappings);
-       ast_cli_register(&cli_show_precache);
-       ast_cli_register(&cli_show_peer);
-       ast_cli_register(&cli_lookup);
-       ast_cli_register(&cli_precache);
-       ast_cli_register(&cli_queryeid);
-       if (ast_register_switch(&dundi_switch))
-               ast_log(LOG_ERROR, "Unable to register DUNDi switch\n");
-
-       set_config("dundi.conf",&sin);
+       if (set_config("dundi.conf", &sin))
+               return AST_MODULE_LOAD_DECLINE;
 
        netsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
        
        if (netsocket < 0) {
                ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno));
-               return -1;
+               return AST_MODULE_LOAD_FAILURE;
        }
-       if (bind(netsocket,(struct sockaddr *)&sin, sizeof(sin))) {
-               ast_log(LOG_ERROR, "Unable to bind to %s port %d: %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port), strerror(errno));
-               return -1;
+       if (bind(netsocket, (struct sockaddr *) &sin, sizeof(sin))) {
+               ast_log(LOG_ERROR, "Unable to bind to %s port %d: %s\n", 
+                       ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), strerror(errno));
+               return AST_MODULE_LOAD_FAILURE;
        }
 
        if (option_verbose > 1)
@@ -4669,33 +4556,28 @@ int load_module(void)
        if (setsockopt(netsocket, IPPROTO_IP, IP_TOS, &tos, sizeof(tos))) 
                ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
        
-       if (!res) {
-               res = start_network_thread();
-               if (option_verbose > 1) 
-                       ast_verbose(VERBOSE_PREFIX_2 "DUNDi Ready and Listening on %s port %d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port));
-       } else {
+       if (start_network_thread()) {
                ast_log(LOG_ERROR, "Unable to start network thread\n");
                close(netsocket);
+               return AST_MODULE_LOAD_FAILURE;
+       }
+       
+       ast_cli_register_multiple(cli_dundi, sizeof(cli_dundi) / sizeof(*cli_dundi));
+       if (ast_register_switch(&dundi_switch))
+               ast_log(LOG_ERROR, "Unable to register DUNDi switch\n");
+       ast_custom_function_register(&dundi_function);
+       
+       if (option_verbose > 1) {
+               ast_verbose(VERBOSE_PREFIX_2 "DUNDi Ready and Listening on %s port %d\n", 
+                       ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
        }
-       res = ast_register_application(app, dundi_lookup_exec, synopsis, descrip);
-       return 0;
-}
 
-char *description(void)
-{
-       return tdesc;
+       return AST_MODULE_LOAD_SUCCESS;
 }
 
-int usecount(void)
-{
-       int res;
-       /* XXX DUNDi cannot be unloaded XXX */
-       return 1;
-       STANDARD_USECOUNT(res);
-       return res;
-}
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Distributed Universal Number Discovery (DUNDi)",
+               .load = load_module,
+               .unload = unload_module,
+               .reload = reload,
+              );
 
-char *key()
-{
-       return ASTERISK_GPL_KEY;
-}