Convert all uint32/16/8 to _t in source3/libsmb.
[bbaumbach/samba-autobuild/.git] / source3 / libsmb / namequery.c
index d561049a73807ce85bfd906013f9f99337531a20..8138296f1e3bc106f64930c82779033e9fd30507 100644 (file)
 #include "includes.h"
 #include "../lib/util/tevent_ntstatus.h"
 #include "libads/sitename_cache.h"
-#include "libads/dns.h"
+#include "../lib/addns/dnsquery.h"
 #include "../libcli/netlogon/netlogon.h"
 #include "lib/async_req/async_sock.h"
 #include "libsmb/nmblib.h"
+#include "../libcli/nbt/libnbt.h"
 
 /* nmbd.c sets this to True. */
 bool global_in_nmbd = False;
@@ -43,22 +44,14 @@ bool global_in_nmbd = False;
 #define SAFJOINKEY_FMT "SAFJOIN/DOMAIN/%s"
 #define SAFJOIN_TTL    3600
 
-static char *saf_key(const char *domain)
+static char *saf_key(TALLOC_CTX *mem_ctx, const char *domain)
 {
-       char *keystr;
-
-       asprintf_strupper_m(&keystr, SAFKEY_FMT, domain);
-
-       return keystr;
+       return talloc_asprintf_strupper_m(mem_ctx, SAFKEY_FMT, domain);
 }
 
-static char *saf_join_key(const char *domain)
+static char *saf_join_key(TALLOC_CTX *mem_ctx, const char *domain)
 {
-       char *keystr;
-
-       asprintf_strupper_m(&keystr, SAFJOINKEY_FMT, domain);
-
-       return keystr;
+       return talloc_asprintf_strupper_m(mem_ctx, SAFJOINKEY_FMT, domain);
 }
 
 /****************************************************************************
@@ -82,7 +75,11 @@ bool saf_store( const char *domain, const char *servername )
                return False;
        }
 
-       key = saf_key( domain );
+       key = saf_key(talloc_tos(), domain);
+       if (key == NULL) {
+               DEBUG(1, ("saf_key() failed\n"));
+               return false;
+       }
        expire = time( NULL ) + lp_parm_int(-1, "saf","ttl", SAF_TTL);
 
        DEBUG(10,("saf_store: domain = [%s], server = [%s], expire = [%u]\n",
@@ -90,7 +87,7 @@ bool saf_store( const char *domain, const char *servername )
 
        ret = gencache_set( key, servername, expire );
 
-       SAFE_FREE( key );
+       TALLOC_FREE( key );
 
        return ret;
 }
@@ -111,7 +108,11 @@ bool saf_join_store( const char *domain, const char *servername )
                return False;
        }
 
-       key = saf_join_key( domain );
+       key = saf_join_key(talloc_tos(), domain);
+       if (key == NULL) {
+               DEBUG(1, ("saf_join_key() failed\n"));
+               return false;
+       }
        expire = time( NULL ) + lp_parm_int(-1, "saf","join ttl", SAFJOIN_TTL);
 
        DEBUG(10,("saf_join_store: domain = [%s], server = [%s], expire = [%u]\n",
@@ -119,7 +120,7 @@ bool saf_join_store( const char *domain, const char *servername )
 
        ret = gencache_set( key, servername, expire );
 
-       SAFE_FREE( key );
+       TALLOC_FREE( key );
 
        return ret;
 }
@@ -134,17 +135,25 @@ bool saf_delete( const char *domain )
                return False;
        }
 
-       key = saf_join_key(domain);
+       key = saf_join_key(talloc_tos(), domain);
+       if (key == NULL) {
+               DEBUG(1, ("saf_join_key() failed\n"));
+               return false;
+       }
        ret = gencache_del(key);
-       SAFE_FREE(key);
+       TALLOC_FREE(key);
 
        if (ret) {
                DEBUG(10,("saf_delete[join]: domain = [%s]\n", domain ));
        }
 
-       key = saf_key(domain);
+       key = saf_key(talloc_tos(), domain);
+       if (key == NULL) {
+               DEBUG(1, ("saf_key() failed\n"));
+               return false;
+       }
        ret = gencache_del(key);
-       SAFE_FREE(key);
+       TALLOC_FREE(key);
 
        if (ret) {
                DEBUG(10,("saf_delete: domain = [%s]\n", domain ));
@@ -156,7 +165,7 @@ bool saf_delete( const char *domain )
 /****************************************************************************
 ****************************************************************************/
 
-char *saf_fetch( const char *domain )
+char *saf_fetch(TALLOC_CTX *mem_ctx, const char *domain )
 {
        char *server = NULL;
        time_t timeout;
@@ -168,11 +177,15 @@ char *saf_fetch( const char *domain )
                return NULL;
        }
 
-       key = saf_join_key( domain );
+       key = saf_join_key(talloc_tos(), domain);
+       if (key == NULL) {
+               DEBUG(1, ("saf_join_key() failed\n"));
+               return NULL;
+       }
 
-       ret = gencache_get( key, &server, &timeout );
+       ret = gencache_get( key, mem_ctx, &server, &timeout );
 
-       SAFE_FREE( key );
+       TALLOC_FREE( key );
 
        if ( ret ) {
                DEBUG(5,("saf_fetch[join]: Returning \"%s\" for \"%s\" domain\n",
@@ -180,11 +193,15 @@ char *saf_fetch( const char *domain )
                return server;
        }
 
-       key = saf_key( domain );
+       key = saf_key(talloc_tos(), domain);
+       if (key == NULL) {
+               DEBUG(1, ("saf_key() failed\n"));
+               return NULL;
+       }
 
-       ret = gencache_get( key, &server, &timeout );
+       ret = gencache_get( key, mem_ctx, &server, &timeout );
 
-       SAFE_FREE( key );
+       TALLOC_FREE( key );
 
        if ( !ret ) {
                DEBUG(5,("saf_fetch: failed to find server for \"%s\" domain\n",
@@ -199,7 +216,7 @@ char *saf_fetch( const char *domain )
 
 static void set_socket_addr_v4(struct sockaddr_storage *addr)
 {
-       if (!interpret_string_addr(addr, lp_socket_address(),
+       if (!interpret_string_addr(addr, lp_nbt_client_socket_address(),
                                   AI_NUMERICHOST|AI_PASSIVE)) {
                zero_sockaddr(addr);
        }
@@ -208,15 +225,24 @@ static void set_socket_addr_v4(struct sockaddr_storage *addr)
        }
 }
 
+static struct in_addr my_socket_addr_v4(void)
+{
+       struct sockaddr_storage my_addr;
+       struct sockaddr_in *in_addr = (struct sockaddr_in *)((char *)&my_addr);
+
+       set_socket_addr_v4(&my_addr);
+       return in_addr->sin_addr;
+}
+
 /****************************************************************************
  Generate a random trn_id.
 ****************************************************************************/
 
 static int generate_trn_id(void)
 {
-       uint16 id;
+       uint16_t id;
 
-       generate_random_buffer((uint8 *)&id, sizeof(id));
+       generate_random_buffer((uint8_t *)&id, sizeof(id));
 
        return id % (unsigned)0x7FFF;
 }
@@ -237,7 +263,7 @@ static struct node_status *parse_node_status(TALLOC_CTX *mem_ctx, char *p,
        if (*num_names == 0)
                return NULL;
 
-       ret = TALLOC_ARRAY(mem_ctx, struct node_status,*num_names);
+       ret = talloc_array(mem_ctx, struct node_status,*num_names);
        if (!ret)
                return NULL;
 
@@ -841,7 +867,7 @@ NTSTATUS node_status_query(TALLOC_CTX *mem_ctx, struct nmb_name *name,
        struct tevent_req *req;
        NTSTATUS status = NT_STATUS_NO_MEMORY;
 
-       ev = tevent_context_init(frame);
+       ev = samba_tevent_context_init(frame);
        if (ev == NULL) {
                goto fail;
        }
@@ -1029,7 +1055,7 @@ static int addr_compare(const struct sockaddr_storage *ss1,
  compare 2 ldap IPs by nearness to our interfaces - used in qsort
 *******************************************************************/
 
-int ip_service_compare(struct ip_service *ss1, struct ip_service *ss2)
+static int ip_service_compare(struct ip_service *ss1, struct ip_service *ss2)
 {
        int result;
 
@@ -1076,39 +1102,39 @@ static void sort_service_list(struct ip_service *servlist, int count)
  Remove any duplicate address/port pairs in the list
  *********************************************************************/
 
-static int remove_duplicate_addrs2(struct ip_service *iplist, int count )
+int remove_duplicate_addrs2(struct ip_service *iplist, int count )
 {
        int i, j;
 
        DEBUG(10,("remove_duplicate_addrs2: "
                        "looking for duplicate address/port pairs\n"));
 
-       /* one loop to remove duplicates */
+       /* One loop to set duplicates to a zero addr. */
        for ( i=0; i<count; i++ ) {
                if ( is_zero_addr(&iplist[i].ss)) {
                        continue;
                }
 
                for ( j=i+1; j<count; j++ ) {
-                       if (sockaddr_equal((struct sockaddr *)&iplist[i].ss, (struct sockaddr *)&iplist[j].ss) &&
+                       if (sockaddr_equal((struct sockaddr *)(void *)&iplist[i].ss,
+                                          (struct sockaddr *)(void *)&iplist[j].ss) &&
                                        iplist[i].port == iplist[j].port) {
                                zero_sockaddr(&iplist[j].ss);
                        }
                }
        }
 
-       /* one loop to clean up any holes we left */
-       /* first ip should never be a zero_ip() */
-       for (i = 0; i<count; ) {
-               if (is_zero_addr(&iplist[i].ss) ) {
-                       if (i != count-1) {
-                               memmove(&iplist[i], &iplist[i+1],
-                                       (count - i - 1)*sizeof(iplist[i]));
+       /* Now remove any addresses set to zero above. */
+       for (i = 0; i < count; i++) {
+               while (i < count &&
+                               is_zero_addr(&iplist[i].ss)) {
+                       if (count-i-1>0) {
+                               memmove(&iplist[i],
+                                       &iplist[i+1],
+                                       (count-i-1)*sizeof(struct ip_service));
                        }
                        count--;
-                       continue;
                }
-               i++;
        }
 
        return count;
@@ -1117,7 +1143,7 @@ static int remove_duplicate_addrs2(struct ip_service *iplist, int count )
 static bool prioritize_ipv4_list(struct ip_service *iplist, int count)
 {
        TALLOC_CTX *frame = talloc_stackframe();
-       struct ip_service *iplist_new = TALLOC_ARRAY(frame, struct ip_service, count);
+       struct ip_service *iplist_new = talloc_array(frame, struct ip_service, count);
        int i, j;
 
        if (iplist_new == NULL) {
@@ -1317,7 +1343,7 @@ static bool name_query_validator(struct packet_struct *p, void *private_data)
                return false;
        }
 
-       tmp_addrs = TALLOC_REALLOC_ARRAY(
+       tmp_addrs = talloc_realloc(
                state, state->addrs, struct sockaddr_storage,
                state->num_addrs + nmb->answers->rdlength/6);
        if (tmp_addrs == NULL) {
@@ -1341,10 +1367,14 @@ static bool name_query_validator(struct packet_struct *p, void *private_data)
                putip((char *)&ip,&nmb->answers->rdata[2+i*6]);
                in_addr_to_sockaddr_storage(&addr, ip);
 
+               if (is_zero_addr(&addr)) {
+                       continue;
+               }
+
                for (j=0; j<state->num_addrs; j++) {
                        if (sockaddr_equal(
-                                   (struct sockaddr *)&addr,
-                                   (struct sockaddr *)&state->addrs[j])) {
+                                   (struct sockaddr *)(void *)&addr,
+                                   (struct sockaddr *)(void *)&state->addrs[j])) {
                                break;
                        }
                }
@@ -1423,9 +1453,18 @@ NTSTATUS name_query_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
                req, struct name_query_state);
        NTSTATUS status;
 
-       if (tevent_req_is_nterror(req, &status)
-           && !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
-               return status;
+       if (tevent_req_is_nterror(req, &status)) {
+               if (state->bcast &&
+                   NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
+                       /*
+                        * In the broadcast case we collect replies until the
+                        * timeout.
+                        */
+                       status = NT_STATUS_OK;
+               }
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
        }
        if (state->num_addrs == 0) {
                return NT_STATUS_NOT_FOUND;
@@ -1452,7 +1491,7 @@ NTSTATUS name_query(const char *name, int name_type,
        struct timeval timeout;
        NTSTATUS status = NT_STATUS_NO_MEMORY;
 
-       ev = tevent_context_init(frame);
+       ev = samba_tevent_context_init(frame);
        if (ev == NULL) {
                goto fail;
        }
@@ -1478,32 +1517,53 @@ NTSTATUS name_query(const char *name, int name_type,
 }
 
 /********************************************************
convert an array if struct sockaddr_storage to struct ip_service
Convert an array if struct sockaddr_storage to struct ip_service
  return false on failure.  Port is set to PORT_NONE;
+ pcount is [in/out] - it is the length of ss_list on input,
+ and the length of return_iplist on output as we remove any
+ zero addresses from ss_list.
 *********************************************************/
 
 static bool convert_ss2service(struct ip_service **return_iplist,
                const struct sockaddr_storage *ss_list,
-               int count)
+               int *pcount)
 {
        int i;
+       int orig_count = *pcount;
+       int real_count = 0;
 
-       if ( count==0 || !ss_list )
+       if (orig_count==0 || !ss_list )
                return False;
 
+       /* Filter out zero addrs. */
+       for ( i=0; i<orig_count; i++ ) {
+               if (is_zero_addr(&ss_list[i])) {
+                       continue;
+               }
+               real_count++;
+       }
+       if (real_count==0) {
+               return false;
+       }
+
        /* copy the ip address; port will be PORT_NONE */
-       if ((*return_iplist = SMB_MALLOC_ARRAY(struct ip_service, count)) ==
+       if ((*return_iplist = SMB_MALLOC_ARRAY(struct ip_service, real_count)) ==
                        NULL) {
                DEBUG(0,("convert_ip2service: malloc failed "
-                       "for %d enetries!\n", count ));
+                       "for %d enetries!\n", real_count ));
                return False;
        }
 
-       for ( i=0; i<count; i++ ) {
-               (*return_iplist)[i].ss   = ss_list[i];
-               (*return_iplist)[i].port = PORT_NONE;
+       for ( i=0, real_count = 0; i<orig_count; i++ ) {
+               if (is_zero_addr(&ss_list[i])) {
+                       continue;
+               }
+               (*return_iplist)[real_count].ss   = ss_list[i];
+               (*return_iplist)[real_count].port = PORT_NONE;
+               real_count++;
        }
 
+       *pcount = real_count;
        return true;
 }
 
@@ -1576,7 +1636,7 @@ static struct tevent_req *name_queries_send(
        if (!tevent_req_set_endtime(
                    subreq, state->ev,
                    timeval_current_ofs(0, state->timeout_msec * 1000))) {
-               tevent_req_nomem(NULL, req);
+               tevent_req_oom(req);
                return tevent_req_post(req, ev);
        }
        tevent_req_set_callback(subreq, name_queries_done, req);
@@ -1659,7 +1719,7 @@ static void name_queries_next(struct tevent_req *subreq)
        if (!tevent_req_set_endtime(
                    subreq, state->ev,
                    timeval_current_ofs(0, state->timeout_msec * 1000))) {
-               tevent_req_nomem(NULL, req);
+               tevent_req_oom(req);
                return;
        }
        state->subreqs[state->num_sent] = subreq;
@@ -1704,142 +1764,314 @@ static NTSTATUS name_queries_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
        return NT_STATUS_OK;
 }
 
-static NTSTATUS name_queries(const char *name, int name_type,
-                            bool bcast, bool recurse,
-                            const struct sockaddr_storage *addrs,
-                            int num_addrs, int wait_msec, int timeout_msec,
-                            TALLOC_CTX *mem_ctx,
-                            struct sockaddr_storage **result_addrs,
-                            int *num_result_addrs, uint8_t *flags,
-                            int *received_index)
+/********************************************************
+ Resolve via "bcast" method.
+*********************************************************/
+
+struct name_resolve_bcast_state {
+       struct sockaddr_storage *addrs;
+       int num_addrs;
+};
+
+static void name_resolve_bcast_done(struct tevent_req *subreq);
+
+struct tevent_req *name_resolve_bcast_send(TALLOC_CTX *mem_ctx,
+                                          struct tevent_context *ev,
+                                          const char *name,
+                                          int name_type)
+{
+       struct tevent_req *req, *subreq;
+       struct name_resolve_bcast_state *state;
+       struct sockaddr_storage *bcast_addrs;
+       int i, num_addrs, num_bcast_addrs;
+
+       req = tevent_req_create(mem_ctx, &state,
+                               struct name_resolve_bcast_state);
+       if (req == NULL) {
+               return NULL;
+       }
+
+       if (lp_disable_netbios()) {
+               DEBUG(5, ("name_resolve_bcast(%s#%02x): netbios is disabled\n",
+                         name, name_type));
+               tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return tevent_req_post(req, ev);
+       }
+
+       /*
+        * "bcast" means do a broadcast lookup on all the local interfaces.
+        */
+
+       DEBUG(3, ("name_resolve_bcast: Attempting broadcast lookup "
+                 "for name %s<0x%x>\n", name, name_type));
+
+       num_addrs = iface_count();
+       bcast_addrs = talloc_array(state, struct sockaddr_storage, num_addrs);
+       if (tevent_req_nomem(bcast_addrs, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       /*
+        * Lookup the name on all the interfaces, return on
+        * the first successful match.
+        */
+       num_bcast_addrs = 0;
+
+       for (i=0; i<num_addrs; i++) {
+               const struct sockaddr_storage *pss = iface_n_bcast(i);
+
+               if (pss->ss_family != AF_INET) {
+                       continue;
+               }
+               bcast_addrs[num_bcast_addrs] = *pss;
+               num_bcast_addrs += 1;
+       }
+
+       subreq = name_queries_send(state, ev, name, name_type, true, true,
+                                  bcast_addrs, num_bcast_addrs, 0, 1000);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+       tevent_req_set_callback(subreq, name_resolve_bcast_done, req);
+       return req;
+}
+
+static void name_resolve_bcast_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct name_resolve_bcast_state *state = tevent_req_data(
+               req, struct name_resolve_bcast_state);
+       NTSTATUS status;
+
+       status = name_queries_recv(subreq, state,
+                                  &state->addrs, &state->num_addrs,
+                                  NULL, NULL);
+       TALLOC_FREE(subreq);
+       if (tevent_req_nterror(req, status)) {
+               return;
+       }
+       tevent_req_done(req);
+}
+
+NTSTATUS name_resolve_bcast_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+                                struct sockaddr_storage **addrs,
+                                int *num_addrs)
+{
+       struct name_resolve_bcast_state *state = tevent_req_data(
+               req, struct name_resolve_bcast_state);
+       NTSTATUS status;
+
+       if (tevent_req_is_nterror(req, &status)) {
+               return status;
+       }
+       *addrs = talloc_move(mem_ctx, &state->addrs);
+       *num_addrs = state->num_addrs;
+       return NT_STATUS_OK;
+}
+
+NTSTATUS name_resolve_bcast(const char *name,
+                       int name_type,
+                       TALLOC_CTX *mem_ctx,
+                       struct sockaddr_storage **return_iplist,
+                       int *return_count)
 {
        TALLOC_CTX *frame = talloc_stackframe();
-       struct event_context *ev;
+       struct tevent_context *ev;
        struct tevent_req *req;
        NTSTATUS status = NT_STATUS_NO_MEMORY;
 
-       ev = event_context_init(frame);
+       ev = samba_tevent_context_init(frame);
        if (ev == NULL) {
                goto fail;
        }
-       req = name_queries_send(frame, ev, name, name_type, bcast,
-                               recurse, addrs, num_addrs, wait_msec,
-                               timeout_msec);
+       req = name_resolve_bcast_send(frame, ev, name, name_type);
        if (req == NULL) {
                goto fail;
        }
        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
                goto fail;
        }
-       status = name_queries_recv(req, mem_ctx, result_addrs,
-                                  num_result_addrs, flags, received_index);
+       status = name_resolve_bcast_recv(req, mem_ctx, return_iplist,
+                                        return_count);
  fail:
        TALLOC_FREE(frame);
        return status;
 }
 
-/********************************************************
- Resolve via "bcast" method.
-*********************************************************/
+struct query_wins_list_state {
+       struct tevent_context *ev;
+       const char *name;
+       uint8_t name_type;
+       struct in_addr *servers;
+       uint32_t num_servers;
+       struct sockaddr_storage server;
+       uint32_t num_sent;
 
-NTSTATUS name_resolve_bcast(const char *name,
-                       int name_type,
-                       TALLOC_CTX *mem_ctx,
-                       struct sockaddr_storage **return_iplist,
-                       int *return_count)
+       struct sockaddr_storage *addrs;
+       int num_addrs;
+       uint8_t flags;
+};
+
+static void query_wins_list_done(struct tevent_req *subreq);
+
+/*
+ * Query a list of (replicating) wins servers in sequence, call them
+ * dead if they don't reply
+ */
+
+static struct tevent_req *query_wins_list_send(
+       TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+       struct in_addr src_ip, const char *name, uint8_t name_type,
+       struct in_addr *servers, int num_servers)
 {
-       int i;
-       int num_interfaces = iface_count();
-       struct sockaddr_storage *ss_list;
-       NTSTATUS status = NT_STATUS_NOT_FOUND;
+       struct tevent_req *req, *subreq;
+       struct query_wins_list_state *state;
 
-       if (lp_disable_netbios()) {
-               DEBUG(5,("name_resolve_bcast(%s#%02x): netbios is disabled\n",
-                                       name, name_type));
-               return NT_STATUS_INVALID_PARAMETER;
+       req = tevent_req_create(mem_ctx, &state,
+                               struct query_wins_list_state);
+       if (req == NULL) {
+               return NULL;
        }
+       state->ev = ev;
+       state->name = name;
+       state->name_type = name_type;
+       state->servers = servers;
+       state->num_servers = num_servers;
 
-       *return_iplist = NULL;
-       *return_count = 0;
+       if (state->num_servers == 0) {
+               tevent_req_nterror(req, NT_STATUS_NOT_FOUND);
+               return tevent_req_post(req, ev);
+       }
 
-       /*
-        * "bcast" means do a broadcast lookup on all the local interfaces.
-        */
+       in_addr_to_sockaddr_storage(
+               &state->server, state->servers[state->num_sent]);
 
-       DEBUG(3,("name_resolve_bcast: Attempting broadcast lookup "
-               "for name %s<0x%x>\n", name, name_type));
+       subreq = name_query_send(state, state->ev,
+                                state->name, state->name_type,
+                                false, true, &state->server);
+       state->num_sent += 1;
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+       if (!tevent_req_set_endtime(subreq, state->ev,
+                                   timeval_current_ofs(2, 0))) {
+               tevent_req_oom(req);
+               return tevent_req_post(req, ev);
+       }
+       tevent_req_set_callback(subreq, query_wins_list_done, req);
+       return req;
+}
 
-       /*
-        * Lookup the name on all the interfaces, return on
-        * the first successful match.
-        */
-       for( i = num_interfaces-1; i >= 0; i--) {
-               const struct sockaddr_storage *pss = iface_n_bcast(i);
+static void query_wins_list_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct query_wins_list_state *state = tevent_req_data(
+               req, struct query_wins_list_state);
+       NTSTATUS status;
 
-               /* Done this way to fix compiler error on IRIX 5.x */
-               if (!pss) {
-                       continue;
-               }
-               status = name_query(name, name_type, true, true, pss,
-                                   talloc_tos(), &ss_list, return_count,
-                                   NULL);
-               if (NT_STATUS_IS_OK(status)) {
-                       goto success;
-               }
+       status = name_query_recv(subreq, state,
+                                &state->addrs, &state->num_addrs,
+                                &state->flags);
+       TALLOC_FREE(subreq);
+       if (NT_STATUS_IS_OK(status)) {
+               tevent_req_done(req);
+               return;
+       }
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
+               tevent_req_nterror(req, status);
+               return;
        }
+       wins_srv_died(state->servers[state->num_sent-1],
+                     my_socket_addr_v4());
 
-       /* failed - no response */
+       if (state->num_sent == state->num_servers) {
+               tevent_req_nterror(req, NT_STATUS_NOT_FOUND);
+               return;
+       }
 
-       return status;
+       in_addr_to_sockaddr_storage(
+               &state->server, state->servers[state->num_sent]);
 
-success:
-       *return_iplist = ss_list;
-       return status;
+       subreq = name_query_send(state, state->ev,
+                                state->name, state->name_type,
+                                false, true, &state->server);
+       state->num_sent += 1;
+       if (tevent_req_nomem(subreq, req)) {
+               return;
+       }
+       if (!tevent_req_set_endtime(subreq, state->ev,
+                                   timeval_current_ofs(2, 0))) {
+               tevent_req_oom(req);
+               return;
+       }
+       tevent_req_set_callback(subreq, query_wins_list_done, req);
 }
 
-/********************************************************
- Resolve via "wins" method.
-*********************************************************/
-
-NTSTATUS resolve_wins(const char *name,
-               int name_type,
-               struct ip_service **return_iplist,
-               int *return_count)
+static NTSTATUS query_wins_list_recv(struct tevent_req *req,
+                                    TALLOC_CTX *mem_ctx,
+                                    struct sockaddr_storage **addrs,
+                                    int *num_addrs,
+                                    uint8_t *flags)
 {
-       int t, i;
-       char **wins_tags;
-       struct sockaddr_storage src_ss, *ss_list = NULL;
-       struct in_addr src_ip;
+       struct query_wins_list_state *state = tevent_req_data(
+               req, struct query_wins_list_state);
        NTSTATUS status;
 
-       if (lp_disable_netbios()) {
-               DEBUG(5,("resolve_wins(%s#%02x): netbios is disabled\n",
-                                       name, name_type));
-               return NT_STATUS_INVALID_PARAMETER;
+       if (tevent_req_is_nterror(req, &status)) {
+               return status;
+       }
+       if (addrs != NULL) {
+               *addrs = talloc_move(mem_ctx, &state->addrs);
+       }
+       if (num_addrs != NULL) {
+               *num_addrs = state->num_addrs;
        }
+       if (flags != NULL) {
+               *flags = state->flags;
+       }
+       return NT_STATUS_OK;
+}
 
-       *return_iplist = NULL;
-       *return_count = 0;
+struct resolve_wins_state {
+       int num_sent;
+       int num_received;
 
-       DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n",
-                               name, name_type));
+       struct sockaddr_storage *addrs;
+       int num_addrs;
+       uint8_t flags;
+};
+
+static void resolve_wins_done(struct tevent_req *subreq);
+
+struct tevent_req *resolve_wins_send(TALLOC_CTX *mem_ctx,
+                                    struct tevent_context *ev,
+                                    const char *name,
+                                    int name_type)
+{
+       struct tevent_req *req, *subreq;
+       struct resolve_wins_state *state;
+       char **wins_tags = NULL;
+       struct sockaddr_storage src_ss;
+       struct in_addr src_ip;
+       int i, num_wins_tags;
+
+       req = tevent_req_create(mem_ctx, &state,
+                               struct resolve_wins_state);
+       if (req == NULL) {
+               return NULL;
+       }
 
        if (wins_srv_count() < 1) {
                DEBUG(3,("resolve_wins: WINS server resolution selected "
                        "and no WINS servers listed.\n"));
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       /* we try a lookup on each of the WINS tags in turn */
-       wins_tags = wins_srv_tags();
-
-       if (!wins_tags) {
-               /* huh? no tags?? give up in disgust */
-               return NT_STATUS_INVALID_PARAMETER;
+               tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               goto fail;
        }
 
        /* the address we will be sending from */
-       if (!interpret_string_addr(&src_ss, lp_socket_address(),
+       if (!interpret_string_addr(&src_ss, lp_nbt_client_socket_address(),
                                AI_NUMERICHOST|AI_PASSIVE)) {
                zero_sockaddr(&src_ss);
        }
@@ -1850,80 +2082,164 @@ NTSTATUS resolve_wins(const char *name,
                DEBUG(3,("resolve_wins: cannot receive WINS replies "
                        "on IPv6 address %s\n",
                        addr));
-               wins_srv_tags_free(wins_tags);
-               return NT_STATUS_INVALID_PARAMETER;
+               tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               goto fail;
+       }
+
+       src_ip = ((const struct sockaddr_in *)(void *)&src_ss)->sin_addr;
+
+       wins_tags = wins_srv_tags();
+       if (wins_tags == NULL) {
+               tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               goto fail;
        }
 
-       src_ip = ((struct sockaddr_in *)&src_ss)->sin_addr;
+       num_wins_tags = 0;
+       while (wins_tags[num_wins_tags] != NULL) {
+               num_wins_tags += 1;
+       }
+
+       for (i=0; i<num_wins_tags; i++) {
+               int num_servers, num_alive;
+               struct in_addr *servers, *alive;
+               int j;
+
+               if (!wins_server_tag_ips(wins_tags[i], talloc_tos(),
+                                        &servers, &num_servers)) {
+                       DEBUG(10, ("wins_server_tag_ips failed for tag %s\n",
+                                  wins_tags[i]));
+                       continue;
+               }
 
-       /* in the worst case we will try every wins server with every
-          tag! */
-       for (t=0; wins_tags && wins_tags[t]; t++) {
-               int srv_count = wins_srv_count_tag(wins_tags[t]);
-               for (i=0; i<srv_count; i++) {
-                       struct sockaddr_storage wins_ss;
-                       struct in_addr wins_ip;
+               alive = talloc_array(state, struct in_addr, num_servers);
+               if (tevent_req_nomem(alive, req)) {
+                       goto fail;
+               }
 
-                       wins_ip = wins_srv_ip_tag(wins_tags[t], src_ip);
+               num_alive = 0;
+               for (j=0; j<num_servers; j++) {
+                       struct in_addr wins_ip = servers[j];
 
                        if (global_in_nmbd && ismyip_v4(wins_ip)) {
                                /* yikes! we'll loop forever */
                                continue;
                        }
-
                        /* skip any that have been unresponsive lately */
                        if (wins_srv_is_dead(wins_ip, src_ip)) {
                                continue;
                        }
+                       DEBUG(3, ("resolve_wins: using WINS server %s "
+                                "and tag '%s'\n",
+                                 inet_ntoa(wins_ip), wins_tags[i]));
+                       alive[num_alive] = wins_ip;
+                       num_alive += 1;
+               }
+               TALLOC_FREE(servers);
 
-                       DEBUG(3,("resolve_wins: using WINS server %s "
-                               "and tag '%s'\n",
-                               inet_ntoa(wins_ip), wins_tags[t]));
+               if (num_alive == 0) {
+                       continue;
+               }
 
-                       in_addr_to_sockaddr_storage(&wins_ss, wins_ip);
-                       status = name_query(name,
-                                               name_type,
-                                               false,
-                                               true,
-                                               &wins_ss,
-                                               talloc_tos(),
-                                               &ss_list,
-                                               return_count,
-                                               NULL);
+               subreq = query_wins_list_send(
+                       state, ev, src_ip, name, name_type,
+                       alive, num_alive);
+               if (tevent_req_nomem(subreq, req)) {
+                       goto fail;
+               }
+               tevent_req_set_callback(subreq, resolve_wins_done, req);
+               state->num_sent += 1;
+       }
 
-                       /* exit loop if we got a list of addresses */
+       if (state->num_sent == 0) {
+               tevent_req_nterror(req, NT_STATUS_NOT_FOUND);
+               goto fail;
+       }
 
-                       if (NT_STATUS_IS_OK(status)) {
-                               goto success;
-                       }
+       wins_srv_tags_free(wins_tags);
+       return req;
+fail:
+       wins_srv_tags_free(wins_tags);
+       return tevent_req_post(req, ev);
+}
 
-                       if (NT_STATUS_EQUAL(status,
-                                           NT_STATUS_IO_TIMEOUT)) {
-                               /* Timed out waiting for WINS server to
-                                * respond.
-                                * Mark it dead. */
-                               wins_srv_died(wins_ip, src_ip);
-                       } else {
-                               /* The name definitely isn't in this
-                                  group of WINS servers.
-                                  goto the next group  */
-                               break;
-                       }
-               }
+static void resolve_wins_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct resolve_wins_state *state = tevent_req_data(
+               req, struct resolve_wins_state);
+       NTSTATUS status;
+
+       status = query_wins_list_recv(subreq, state, &state->addrs,
+                                     &state->num_addrs, &state->flags);
+       if (NT_STATUS_IS_OK(status)) {
+               tevent_req_done(req);
+               return;
        }
 
-       wins_srv_tags_free(wins_tags);
-       return NT_STATUS_NO_LOGON_SERVERS;
+       state->num_received += 1;
 
-success:
+       if (state->num_received < state->num_sent) {
+               /*
+                * Wait for the others
+                */
+               return;
+       }
+       tevent_req_nterror(req, status);
+}
 
-       status = NT_STATUS_OK;
-       if (!convert_ss2service(return_iplist, ss_list, *return_count))
-               status = NT_STATUS_INVALID_PARAMETER;
+NTSTATUS resolve_wins_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+                          struct sockaddr_storage **addrs,
+                          int *num_addrs, uint8_t *flags)
+{
+       struct resolve_wins_state *state = tevent_req_data(
+               req, struct resolve_wins_state);
+       NTSTATUS status;
 
-       TALLOC_FREE(ss_list);
-       wins_srv_tags_free(wins_tags);
+       if (tevent_req_is_nterror(req, &status)) {
+               return status;
+       }
+       if (addrs != NULL) {
+               *addrs = talloc_move(mem_ctx, &state->addrs);
+       }
+       if (num_addrs != NULL) {
+               *num_addrs = state->num_addrs;
+       }
+       if (flags != NULL) {
+               *flags = state->flags;
+       }
+       return NT_STATUS_OK;
+}
+
+/********************************************************
+ Resolve via "wins" method.
+*********************************************************/
 
+NTSTATUS resolve_wins(const char *name,
+               int name_type,
+               TALLOC_CTX *mem_ctx,
+               struct sockaddr_storage **return_iplist,
+               int *return_count)
+{
+       struct tevent_context *ev;
+       struct tevent_req *req;
+       NTSTATUS status = NT_STATUS_NO_MEMORY;
+
+       ev = samba_tevent_context_init(talloc_tos());
+       if (ev == NULL) {
+               goto fail;
+       }
+       req = resolve_wins_send(ev, ev, name, name_type);
+       if (req == NULL) {
+               goto fail;
+       }
+       if (!tevent_req_poll_ntstatus(req, ev, &status)) {
+               goto fail;
+       }
+       status = resolve_wins_recv(req, mem_ctx, return_iplist, return_count,
+                                  NULL);
+fail:
+       TALLOC_FREE(ev);
        return status;
 }
 
@@ -1962,7 +2278,7 @@ static NTSTATUS resolve_lmhosts(const char *name, int name_type,
        if (NT_STATUS_IS_OK(status)) {
                if (convert_ss2service(return_iplist, 
                                       ss_list,
-                                      *return_count)) {
+                                      return_count)) {
                        talloc_free(ctx);
                        return NT_STATUS_OK;
                } else {
@@ -1991,7 +2307,6 @@ static NTSTATUS resolve_hosts(const char *name, int name_type,
        struct addrinfo *res = NULL;
        int ret = -1;
        int i = 0;
-       const char *dns_hosts_file;
 
        if ( name_type != 0x20 && name_type != 0x0) {
                DEBUG(5, ("resolve_hosts: not appropriate "
@@ -2016,32 +2331,6 @@ static NTSTATUS resolve_hosts(const char *name, int name_type,
        hints.ai_family = AF_INET;
 #endif
 
-       dns_hosts_file = lp_parm_const_string(-1, "resolv", "host file", NULL);
-       if (dns_hosts_file) {
-               struct sockaddr_storage *ss_list;
-               NTSTATUS status;
-               TALLOC_CTX *ctx = talloc_stackframe();
-               if (!ctx) {
-                       return NT_STATUS_NO_MEMORY;
-               }
-
-               status = resolve_dns_hosts_file_as_sockaddr(dns_hosts_file, name, false,
-                                                           ctx, &ss_list, return_count);
-               if (NT_STATUS_IS_OK(status)) {
-                       if (convert_ss2service(return_iplist,
-                                              ss_list,
-                                              *return_count)) {
-                               talloc_free(ctx);
-                               return NT_STATUS_OK;
-                       } else {
-                               talloc_free(ctx);
-                               return NT_STATUS_NO_MEMORY;
-                       }
-               }
-               talloc_free(ctx);
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
        ret = getaddrinfo(name,
                        NULL,
                        &hints,
@@ -2062,6 +2351,10 @@ static NTSTATUS resolve_hosts(const char *name, int name_type,
                ZERO_STRUCT(ss);
                memcpy(&ss, res->ai_addr, res->ai_addrlen);
 
+               if (is_zero_addr(&ss)) {
+                       continue;
+               }
+
                *return_count += 1;
 
                *return_iplist = SMB_REALLOC_ARRAY(*return_iplist,
@@ -2098,7 +2391,7 @@ static NTSTATUS resolve_ads(const char *name,
                            struct ip_service **return_iplist,
                            int *return_count)
 {
-       int                     i, j;
+       int                     i;
        NTSTATUS                status;
        TALLOC_CTX              *ctx;
        struct dns_rr_srv       *dcs = NULL;
@@ -2116,24 +2409,32 @@ static NTSTATUS resolve_ads(const char *name,
        }
 
        /* The DNS code needs fixing to find IPv6 addresses... JRA. */
-
        switch (name_type) {
                case 0x1b:
                        DEBUG(5,("resolve_ads: Attempting to resolve "
                                 "PDC for %s using DNS\n", name));
-                       status = ads_dns_query_pdc(ctx, name, &dcs, &numdcs);
+                       status = ads_dns_query_pdc(ctx,
+                                                  name,
+                                                  &dcs,
+                                                  &numdcs);
                        break;
 
                case 0x1c:
                        DEBUG(5,("resolve_ads: Attempting to resolve "
                                 "DCs for %s using DNS\n", name));
-                       status = ads_dns_query_dcs(ctx, name, sitename, &dcs,
+                       status = ads_dns_query_dcs(ctx,
+                                                  name,
+                                                  sitename,
+                                                  &dcs,
                                                   &numdcs);
                        break;
                case KDC_NAME_TYPE:
                        DEBUG(5,("resolve_ads: Attempting to resolve "
                                 "KDCs for %s using DNS\n", name));
-                       status = ads_dns_query_kdcs(ctx, name, sitename, &dcs,
+                       status = ads_dns_query_kdcs(ctx,
+                                                   name,
+                                                   sitename,
+                                                   &dcs,
                                                    &numdcs);
                        break;
                default:
@@ -2147,8 +2448,12 @@ static NTSTATUS resolve_ads(const char *name,
        }
 
        for (i=0;i<numdcs;i++) {
-               numaddrs += MAX(dcs[i].num_ips,1);
-       }
+               if (!dcs[i].ss_s) {
+                       numaddrs += 1;
+               } else {
+                       numaddrs += dcs[i].num_ips;
+               }
+        }
 
        if ((*return_iplist = SMB_MALLOC_ARRAY(struct ip_service, numaddrs)) ==
                        NULL ) {
@@ -2161,47 +2466,114 @@ static NTSTATUS resolve_ads(const char *name,
        /* now unroll the list of IP addresses */
 
        *return_count = 0;
-       i = 0;
-       j = 0;
-       while ( i < numdcs && (*return_count<numaddrs) ) {
-               struct ip_service *r = &(*return_iplist)[*return_count];
-
-               r->port = dcs[i].port;
 
+       for (i = 0; i < numdcs && (*return_count<numaddrs); i++ ) {
                /* If we don't have an IP list for a name, lookup it up */
-
                if (!dcs[i].ss_s) {
-                       interpret_string_addr(&r->ss, dcs[i].hostname, 0);
-                       i++;
-                       j = 0;
-               } else {
-                       /* use the IP addresses from the SRV sresponse */
-
-                       if ( j >= dcs[i].num_ips ) {
-                               i++;
-                               j = 0;
+                       /* We need to get all IP addresses here. */
+                       struct addrinfo *res = NULL;
+                       struct addrinfo *p;
+                       int extra_addrs = 0;
+
+                       if (!interpret_string_addr_internal(&res,
+                                               dcs[i].hostname,
+                                               0)) {
                                continue;
                        }
-
-                       r->ss = dcs[i].ss_s[j];
-                       j++;
+                       /* Add in every IP from the lookup. How
+                          many is that ? */
+                       for (p = res; p; p = p->ai_next) {
+                               struct sockaddr_storage ss;
+                               memcpy(&ss, p->ai_addr, p->ai_addrlen);
+                               if (is_zero_addr(&ss)) {
+                                       continue;
+                               }
+                               extra_addrs++;
+                       }
+                       if (extra_addrs > 1) {
+                               /* We need to expand the return_iplist array
+                                  as we only budgeted for one address. */
+                               numaddrs += (extra_addrs-1);
+                               *return_iplist = SMB_REALLOC_ARRAY(*return_iplist,
+                                               struct ip_service,
+                                               numaddrs);
+                               if (*return_iplist == NULL) {
+                                       if (res) {
+                                               freeaddrinfo(res);
+                                       }
+                                       talloc_destroy(ctx);
+                                       return NT_STATUS_NO_MEMORY;
+                               }
+                       }
+                       for (p = res; p; p = p->ai_next) {
+                               (*return_iplist)[*return_count].port = dcs[i].port;
+                               memcpy(&(*return_iplist)[*return_count].ss,
+                                               p->ai_addr,
+                                               p->ai_addrlen);
+                               if (is_zero_addr(&(*return_iplist)[*return_count].ss)) {
+                                       continue;
+                               }
+                               (*return_count)++;
+                               /* Should never happen, but still... */
+                               if (*return_count>=numaddrs) {
+                                       break;
+                               }
+                       }
+                       if (res) {
+                               freeaddrinfo(res);
+                       }
+               } else {
+                       /* use all the IP addresses from the SRV sresponse */
+                       int j;
+                       for (j = 0; j < dcs[i].num_ips; j++) {
+                               (*return_iplist)[*return_count].port = dcs[i].port;
+                               (*return_iplist)[*return_count].ss = dcs[i].ss_s[j];
+                               if (is_zero_addr(&(*return_iplist)[*return_count].ss)) {
+                                       continue;
+                               }
+                                (*return_count)++;
+                               /* Should never happen, but still... */
+                               if (*return_count>=numaddrs) {
+                                       break;
+                               }
+                       }
                }
+       }
 
-               /* make sure it is a valid IP.  I considered checking the
-                * negative connection cache, but this is the wrong place
-                * for it. Maybe only as a hack. After think about it, if
-                * all of the IP addresses returned from DNS are dead, what
-                * hope does a netbios name lookup have ? The standard reason
-                * for falling back to netbios lookups is that our DNS server
-                * doesn't know anything about the DC's   -- jerry */
+       talloc_destroy(ctx);
+       return NT_STATUS_OK;
+}
+
+static const char **filter_out_nbt_lookup(TALLOC_CTX *mem_ctx,
+                                         const char **resolve_order)
+{
+       size_t i, len, result_idx;
+       const char **result;
 
-               if (!is_zero_addr(&r->ss)) {
-                       (*return_count)++;
+       len = 0;
+       while (resolve_order[len] != NULL) {
+               len += 1;
+       }
+
+       result = talloc_array(mem_ctx, const char *, len+1);
+       if (result == NULL) {
+               return NULL;
+       }
+
+       result_idx = 0;
+
+       for (i=0; i<len; i++) {
+               const char *tok = resolve_order[i];
+
+               if (strequal(tok, "lmhosts") || strequal(tok, "wins") ||
+                   strequal(tok, "bcast")) {
+                       continue;
                }
+               result[result_idx++] = tok;
        }
+       result[result_idx] = NULL;
 
-       talloc_destroy(ctx);
-       return NT_STATUS_OK;
+       return result;
 }
 
 /*******************************************************************
@@ -2220,10 +2592,9 @@ NTSTATUS internal_resolve_name(const char *name,
                                const char *sitename,
                                struct ip_service **return_iplist,
                                int *return_count,
-                               const char *resolve_order)
+                               const char **resolve_order)
 {
-       char *tok;
-       const char *ptr;
+       const char *tok;
        NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
        int i;
        TALLOC_CTX *frame = NULL;
@@ -2253,6 +2624,10 @@ NTSTATUS internal_resolve_name(const char *name,
                        SAFE_FREE(*return_iplist);
                        return NT_STATUS_INVALID_PARAMETER;
                }
+               if (is_zero_addr(&(*return_iplist)->ss)) {
+                       SAFE_FREE(*return_iplist);
+                       return NT_STATUS_UNSUCCESSFUL;
+               }
                *return_count = 1;
                return NT_STATUS_OK;
        }
@@ -2260,6 +2635,8 @@ NTSTATUS internal_resolve_name(const char *name,
        /* Check name cache */
 
        if (namecache_fetch(name, name_type, return_iplist, return_count)) {
+               *return_count = remove_duplicate_addrs2(*return_iplist,
+                                       *return_count );
                /* This could be a negative response */
                if (*return_count > 0) {
                        return NT_STATUS_OK;
@@ -2270,21 +2647,34 @@ NTSTATUS internal_resolve_name(const char *name,
 
        /* set the name resolution order */
 
-       if (strcmp( resolve_order, "NULL") == 0) {
+       if (resolve_order && strcmp(resolve_order[0], "NULL") == 0) {
                DEBUG(8,("internal_resolve_name: all lookups disabled\n"));
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       if (!resolve_order[0]) {
-               ptr = "host";
-       } else {
-               ptr = resolve_order;
+       if (!resolve_order || !resolve_order[0]) {
+               static const char *host_order[] = { "host", NULL };
+               resolve_order = host_order;
+       }
+
+       frame = talloc_stackframe();
+
+       if ((strlen(name) > MAX_NETBIOSNAME_LEN - 1) ||
+           (strchr(name, '.') != NULL)) {
+               /*
+                * Don't do NBT lookup, the name would not fit anyway
+                */
+               resolve_order = filter_out_nbt_lookup(frame, resolve_order);
+               if (resolve_order == NULL) {
+                       return NT_STATUS_NO_MEMORY;
+               }
        }
 
        /* iterate through the name resolution backends */
 
-       frame = talloc_stackframe();
-       while (next_token_talloc(frame, &ptr, &tok, LIST_SEP)) {
+       for (i=0; resolve_order[i]; i++) {
+               tok = resolve_order[i];
+
                if((strequal(tok, "host") || strequal(tok, "hosts"))) {
                        status = resolve_hosts(name, name_type, return_iplist,
                                               return_count);
@@ -2310,23 +2700,30 @@ NTSTATUS internal_resolve_name(const char *name,
                        if (NT_STATUS_IS_OK(status)) {
                                goto done;
                        }
-               } else if(strequal( tok, "lmhosts")) {
+               } else if (strequal(tok, "lmhosts")) {
                        status = resolve_lmhosts(name, name_type,
                                                 return_iplist, return_count);
                        if (NT_STATUS_IS_OK(status)) {
                                goto done;
                        }
-               } else if(strequal( tok, "wins")) {
+               } else if (strequal(tok, "wins")) {
                        /* don't resolve 1D via WINS */
+                       struct sockaddr_storage *ss_list;
                        if (name_type != 0x1D) {
                                status = resolve_wins(name, name_type,
-                                                     return_iplist,
+                                                     talloc_tos(),
+                                                     &ss_list,
                                                      return_count);
                                if (NT_STATUS_IS_OK(status)) {
+                                       if (!convert_ss2service(return_iplist,
+                                                               ss_list,
+                                                               return_count)) {
+                                               status = NT_STATUS_NO_MEMORY;
+                                       }
                                        goto done;
                                }
                        }
-               } else if(strequal( tok, "bcast")) {
+               } else if (strequal(tok, "bcast")) {
                        struct sockaddr_storage *ss_list;
                        status = name_resolve_bcast(
                                name, name_type, talloc_tos(),
@@ -2334,7 +2731,7 @@ NTSTATUS internal_resolve_name(const char *name,
                        if (NT_STATUS_IS_OK(status)) {
                                if (!convert_ss2service(return_iplist,
                                                        ss_list,
-                                                       *return_count)) {
+                                                       return_count)) {
                                        status = NT_STATUS_NO_MEMORY;
                                }
                                goto done;
@@ -2360,10 +2757,7 @@ NTSTATUS internal_resolve_name(const char *name,
        controllers including the PDC in iplist[1..n].  Iterating over
        the iplist when the PDC is down will cause two sets of timeouts. */
 
-       if ( *return_count ) {
-               *return_count = remove_duplicate_addrs2(*return_iplist,
-                                       *return_count );
-       }
+       *return_count = remove_duplicate_addrs2(*return_iplist, *return_count );
 
        /* Save in name cache */
        if ( DEBUGLEVEL >= 100 ) {
@@ -2379,7 +2773,9 @@ NTSTATUS internal_resolve_name(const char *name,
                }
        }
 
-       namecache_store(name, name_type, *return_count, *return_iplist);
+       if (*return_count) {
+               namecache_store(name, name_type, *return_count, *return_iplist);
+       }
 
        /* Display some debugging info */
 
@@ -2417,26 +2813,28 @@ bool resolve_name(const char *name,
        struct ip_service *ss_list = NULL;
        char *sitename = NULL;
        int count = 0;
+       NTSTATUS status;
 
        if (is_ipaddress(name)) {
                return interpret_string_addr(return_ss, name, AI_NUMERICHOST);
        }
 
-       sitename = sitename_fetch(lp_realm()); /* wild guess */
+       sitename = sitename_fetch(talloc_tos(), lp_realm()); /* wild guess */
 
-       if (NT_STATUS_IS_OK(internal_resolve_name(name, name_type, sitename,
-                                                 &ss_list, &count,
-                                                 lp_name_resolve_order()))) {
+       status = internal_resolve_name(name, name_type, sitename,
+                                      &ss_list, &count,
+                                      lp_name_resolve_order());
+       if (NT_STATUS_IS_OK(status)) {
                int i;
 
                if (prefer_ipv4) {
                        for (i=0; i<count; i++) {
                                if (!is_zero_addr(&ss_list[i].ss) &&
-                                               !is_broadcast_addr((struct sockaddr *)&ss_list[i].ss) &&
+                                   !is_broadcast_addr((struct sockaddr *)(void *)&ss_list[i].ss) &&
                                                (ss_list[i].ss.ss_family == AF_INET)) {
                                        *return_ss = ss_list[i].ss;
                                        SAFE_FREE(ss_list);
-                                       SAFE_FREE(sitename);
+                                       TALLOC_FREE(sitename);
                                        return True;
                                }
                        }
@@ -2445,17 +2843,17 @@ bool resolve_name(const char *name,
                /* only return valid addresses for TCP connections */
                for (i=0; i<count; i++) {
                        if (!is_zero_addr(&ss_list[i].ss) &&
-                                       !is_broadcast_addr((struct sockaddr *)&ss_list[i].ss)) {
+                           !is_broadcast_addr((struct sockaddr *)(void *)&ss_list[i].ss)) {
                                *return_ss = ss_list[i].ss;
                                SAFE_FREE(ss_list);
-                               SAFE_FREE(sitename);
+                               TALLOC_FREE(sitename);
                                return True;
                        }
                }
        }
 
        SAFE_FREE(ss_list);
-       SAFE_FREE(sitename);
+       TALLOC_FREE(sitename);
        return False;
 }
 
@@ -2483,7 +2881,7 @@ NTSTATUS resolve_name_list(TALLOC_CTX *ctx,
        *return_ss_arr = NULL;
 
        if (is_ipaddress(name)) {
-               *return_ss_arr = TALLOC_P(ctx, struct sockaddr_storage);
+               *return_ss_arr = talloc(ctx, struct sockaddr_storage);
                if (!*return_ss_arr) {
                        return NT_STATUS_NO_MEMORY;
                }
@@ -2495,12 +2893,12 @@ NTSTATUS resolve_name_list(TALLOC_CTX *ctx,
                return NT_STATUS_OK;
        }
 
-       sitename = sitename_fetch(lp_realm()); /* wild guess */
+       sitename = sitename_fetch(ctx, lp_realm()); /* wild guess */
 
        status = internal_resolve_name(name, name_type, sitename,
                                                  &ss_list, &count,
                                                  lp_name_resolve_order());
-       SAFE_FREE(sitename);
+       TALLOC_FREE(sitename);
 
        if (!NT_STATUS_IS_OK(status)) {
                return status;
@@ -2509,7 +2907,7 @@ NTSTATUS resolve_name_list(TALLOC_CTX *ctx,
        /* only return valid addresses for TCP connections */
        for (i=0, num_entries = 0; i<count; i++) {
                if (!is_zero_addr(&ss_list[i].ss) &&
-                               !is_broadcast_addr((struct sockaddr *)&ss_list[i].ss)) {
+                   !is_broadcast_addr((struct sockaddr *)(void *)&ss_list[i].ss)) {
                        num_entries++;
                }
        }
@@ -2518,7 +2916,7 @@ NTSTATUS resolve_name_list(TALLOC_CTX *ctx,
                return NT_STATUS_BAD_NETWORK_NAME;
        }
 
-       *return_ss_arr = TALLOC_ARRAY(ctx,
+       *return_ss_arr = talloc_array(ctx,
                                struct sockaddr_storage,
                                num_entries);
        if (!(*return_ss_arr)) {
@@ -2528,7 +2926,7 @@ NTSTATUS resolve_name_list(TALLOC_CTX *ctx,
 
        for (i=0, num_entries = 0; i<count; i++) {
                if (!is_zero_addr(&ss_list[i].ss) &&
-                               !is_broadcast_addr((struct sockaddr *)&ss_list[i].ss)) {
+                   !is_broadcast_addr((struct sockaddr *)(void *)&ss_list[i].ss)) {
                        (*return_ss_arr)[num_entries++] = ss_list[i].ss;
                }
        }
@@ -2585,12 +2983,12 @@ bool get_pdc_ip(const char *domain, struct sockaddr_storage *pss)
        struct ip_service *ip_list = NULL;
        int count = 0;
        NTSTATUS status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
-
+       static const char *ads_order[] = { "ads", NULL };
        /* Look up #1B name */
 
        if (lp_security() == SEC_ADS) {
                status = internal_resolve_name(domain, 0x1b, NULL, &ip_list,
-                                              &count, "ads");
+                                              &count, ads_order);
        }
 
        if (!NT_STATUS_IS_OK(status) || count == 0) {
@@ -2598,6 +2996,7 @@ bool get_pdc_ip(const char *domain, struct sockaddr_storage *pss)
                                               &count,
                                               lp_name_resolve_order());
                if (!NT_STATUS_IS_OK(status)) {
+                       SAFE_FREE(ip_list);
                        return false;
                }
        }
@@ -2631,7 +3030,7 @@ static NTSTATUS get_dc_list(const char *domain,
                        enum dc_lookup_type lookup_type,
                        bool *ordered)
 {
-       char *resolve_order = NULL;
+       const char **resolve_order = NULL;
        char *saf_servername = NULL;
        char *pserver = NULL;
        const char *p;
@@ -2662,27 +3061,30 @@ static NTSTATUS get_dc_list(const char *domain,
           are disabled and ads_only is True, then set the string to
           NULL. */
 
-       resolve_order = talloc_strdup(ctx, lp_name_resolve_order());
+       resolve_order = lp_name_resolve_order();
        if (!resolve_order) {
                status = NT_STATUS_NO_MEMORY;
                goto out;
        }
-       strlower_m(resolve_order);
        if (lookup_type == DC_ADS_ONLY)  {
-               if (strstr( resolve_order, "host")) {
-                       resolve_order = talloc_strdup(ctx, "ads");
+               if (str_list_check_ci(resolve_order, "host")) {
+                       static const char *ads_order[] = { "ads", NULL };
+                       resolve_order = ads_order;
 
                        /* DNS SRV lookups used by the ads resolver
                           are already sorted by priority and weight */
                        *ordered = true;
                } else {
-                        resolve_order = talloc_strdup(ctx, "NULL");
+                       /* this is quite bizarre! */
+                       static const char *null_order[] = { "NULL", NULL };
+                        resolve_order = null_order;
                }
        } else if (lookup_type == DC_KDC_ONLY) {
+               static const char *kdc_order[] = { "kdc", NULL };
                /* DNS SRV lookups used by the ads/kdc resolver
                   are already sorted by priority and weight */
                *ordered = true;
-               resolve_order = talloc_strdup(ctx, "kdc");
+               resolve_order = kdc_order;
        }
        if (!resolve_order) {
                status = NT_STATUS_NO_MEMORY;
@@ -2692,18 +3094,18 @@ static NTSTATUS get_dc_list(const char *domain,
        /* fetch the server we have affinity for.  Add the
           'password server' list to a search for our domain controllers */
 
-       saf_servername = saf_fetch( domain);
+       saf_servername = saf_fetch(ctx, domain);
 
        if (strequal(domain, lp_workgroup()) || strequal(domain, lp_realm())) {
                pserver = talloc_asprintf(ctx, "%s, %s",
                        saf_servername ? saf_servername : "",
-                       lp_passwordserver());
+                       lp_password_server());
        } else {
                pserver = talloc_asprintf(ctx, "%s, *",
                        saf_servername ? saf_servername : "");
        }
 
-       SAFE_FREE(saf_servername);
+       TALLOC_FREE(saf_servername);
        if (!pserver) {
                status = NT_STATUS_NO_MEMORY;
                goto out;
@@ -2748,7 +3150,7 @@ static NTSTATUS get_dc_list(const char *domain,
        /* if we have no addresses and haven't done the auto lookup, then
           just return the list of DC's.  Or maybe we just failed. */
 
-       if ((num_addresses == 0)) {
+       if (num_addresses == 0) {
                if (done_auto_lookup) {
                        DEBUG(4,("get_dc_list: no servers found\n"));
                        status = NT_STATUS_NO_LOGON_SERVERS;
@@ -2842,10 +3244,7 @@ static NTSTATUS get_dc_list(const char *domain,
        /* need to remove duplicates in the list if we have any
           explicit password servers */
 
-       if (local_count) {
-               local_count = remove_duplicate_addrs2(return_iplist,
-                               local_count );
-       }
+       local_count = remove_duplicate_addrs2(return_iplist, local_count );
 
        /* For DC's we always prioritize IPv4 due to W2K3 not
         * supporting LDAP, KRB5 or CLDAP over IPv6. */
@@ -2906,10 +3305,9 @@ NTSTATUS get_sorted_dc_list( const char *domain,
        *count = 0;
 
        DEBUG(8,("get_sorted_dc_list: attempting lookup "
-               "for name %s (sitename %s) using [%s]\n",
+               "for name %s (sitename %s)\n",
                domain,
-               sitename ? sitename : "NULL",
-               (ads_only ? "ads" : lp_name_resolve_order())));
+                sitename ? sitename : "NULL"));
 
        if (ads_only) {
                lookup_type = DC_ADS_ONLY;