lib: remove unused function nttime_from_string()
[bbaumbach/samba-autobuild/.git] / source3 / libsmb / namequery.c
index d86c0ed909fe9948a69980b5d6c287a63bae90f3..abeed972403ab5aae338849f785864517076db6a 100644 (file)
 */
 
 #include "includes.h"
+#include "libsmb/namequery.h"
 #include "../lib/util/tevent_ntstatus.h"
 #include "libads/sitename_cache.h"
 #include "../lib/addns/dnsquery.h"
 #include "../libcli/netlogon/netlogon.h"
 #include "lib/async_req/async_sock.h"
+#include "lib/tsocket/tsocket.h"
 #include "libsmb/nmblib.h"
+#include "libsmb/unexpected.h"
 #include "../libcli/nbt/libnbt.h"
+#include "libads/kerberos_proto.h"
+#include "lib/gencache.h"
 
 /* nmbd.c sets this to True. */
 bool global_in_nmbd = False;
@@ -165,7 +170,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;
@@ -183,7 +188,7 @@ char *saf_fetch( const char *domain )
                return NULL;
        }
 
-       ret = gencache_get( key, &server, &timeout );
+       ret = gencache_get( key, mem_ctx, &server, &timeout );
 
        TALLOC_FREE( key );
 
@@ -199,7 +204,7 @@ char *saf_fetch( const char *domain )
                return NULL;
        }
 
-       ret = gencache_get( key, &server, &timeout );
+       ret = gencache_get( key, mem_ctx, &server, &timeout );
 
        TALLOC_FREE( key );
 
@@ -240,9 +245,9 @@ static struct in_addr my_socket_addr_v4(void)
 
 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;
 }
@@ -269,7 +274,7 @@ static struct node_status *parse_node_status(TALLOC_CTX *mem_ctx, char *p,
 
        p++;
        for (i=0;i< *num_names;i++) {
-               StrnCpy(ret[i].name,p,15);
+               strlcpy(ret[i].name,p,16);
                trim_char(ret[i].name,'\0',' ');
                ret[i].type = CVAL(p,15);
                ret[i].flags = p[16];
@@ -294,11 +299,10 @@ struct sock_packet_read_state {
        struct nb_packet_reader *reader;
        struct tevent_req *reader_req;
 
-       int sock;
+       struct tdgram_context *sock;
        struct tevent_req *socket_req;
-       uint8_t buf[1024];
-       struct sockaddr_storage addr;
-       socklen_t addr_len;
+       uint8_t *buf;
+       struct tsocket_address *addr;
 
        bool (*validator)(struct packet_struct *p,
                          void *private_data);
@@ -307,14 +311,13 @@ struct sock_packet_read_state {
        struct packet_struct *packet;
 };
 
-static int sock_packet_read_state_destructor(struct sock_packet_read_state *s);
 static void sock_packet_read_got_packet(struct tevent_req *subreq);
 static void sock_packet_read_got_socket(struct tevent_req *subreq);
 
 static struct tevent_req *sock_packet_read_send(
        TALLOC_CTX *mem_ctx,
        struct tevent_context *ev,
-       int sock, /* dgram socket */
+       struct tdgram_context *sock,
        struct nb_packet_reader *reader,
        enum packet_type type,
        int trn_id,
@@ -329,7 +332,6 @@ static struct tevent_req *sock_packet_read_send(
        if (req == NULL) {
                return NULL;
        }
-       talloc_set_destructor(state, sock_packet_read_state_destructor);
        state->ev = ev;
        state->reader = reader;
        state->sock = sock;
@@ -347,10 +349,7 @@ static struct tevent_req *sock_packet_read_send(
                        state->reader_req, sock_packet_read_got_packet, req);
        }
 
-       state->addr_len = sizeof(state->addr);
-       state->socket_req = recvfrom_send(state, ev, sock,
-                                         state->buf, sizeof(state->buf), 0,
-                                         &state->addr, &state->addr_len);
+       state->socket_req = tdgram_recvfrom_send(state, ev, state->sock);
        if (tevent_req_nomem(state->socket_req, req)) {
                return tevent_req_post(req, ev);
        }
@@ -360,15 +359,6 @@ static struct tevent_req *sock_packet_read_send(
        return req;
 }
 
-static int sock_packet_read_state_destructor(struct sock_packet_read_state *s)
-{
-       if (s->packet != NULL) {
-               free_packet(s->packet);
-               s->packet = NULL;
-       }
-       return 0;
-}
-
 static void sock_packet_read_got_packet(struct tevent_req *subreq)
 {
        struct tevent_req *req = tevent_req_callback_data(
@@ -377,7 +367,7 @@ static void sock_packet_read_got_packet(struct tevent_req *subreq)
                req, struct sock_packet_read_state);
        NTSTATUS status;
 
-       status = nb_packet_read_recv(subreq, &state->packet);
+       status = nb_packet_read_recv(subreq, state, &state->packet);
 
        TALLOC_FREE(state->reader_req);
 
@@ -399,8 +389,7 @@ static void sock_packet_read_got_packet(struct tevent_req *subreq)
            !state->validator(state->packet, state->private_data)) {
                DEBUG(10, ("validator failed\n"));
 
-               free_packet(state->packet);
-               state->packet = NULL;
+               TALLOC_FREE(state->packet);
 
                state->reader_req = nb_packet_read_send(state, state->ev,
                                                        state->reader);
@@ -422,11 +411,17 @@ static void sock_packet_read_got_socket(struct tevent_req *subreq)
                subreq, struct tevent_req);
        struct sock_packet_read_state *state = tevent_req_data(
                req, struct sock_packet_read_state);
-       struct sockaddr_in *in_addr;
+       union {
+               struct sockaddr sa;
+               struct sockaddr_in sin;
+       } addr;
+       ssize_t ret;
        ssize_t received;
        int err;
+       bool ok;
 
-       received = recvfrom_recv(subreq, &err);
+       received = tdgram_recvfrom_recv(subreq, &err, state,
+                                       &state->buf, &state->addr);
 
        TALLOC_FREE(state->socket_req);
 
@@ -443,13 +438,21 @@ static void sock_packet_read_got_socket(struct tevent_req *subreq)
                tevent_req_nterror(req, map_nt_error_from_unix(err));
                return;
        }
-       if (state->addr.ss_family != AF_INET) {
+       ok = tsocket_address_is_inet(state->addr, "ipv4");
+       if (!ok) {
                goto retry;
        }
-       in_addr = (struct sockaddr_in *)(void *)&state->addr;
+       ret = tsocket_address_bsd_sockaddr(state->addr,
+                                          &addr.sa,
+                                          sizeof(addr.sin));
+       if (ret == -1) {
+               tevent_req_nterror(req, map_nt_error_from_unix(errno));
+               return;
+       }
 
-       state->packet = parse_packet((char *)state->buf, received, state->type,
-                                    in_addr->sin_addr, in_addr->sin_port);
+       state->packet = parse_packet_talloc(
+               state, (char *)state->buf, received, state->type,
+               addr.sin.sin_addr, addr.sin.sin_port);
        if (state->packet == NULL) {
                DEBUG(10, ("parse_packet failed\n"));
                goto retry;
@@ -471,13 +474,11 @@ static void sock_packet_read_got_socket(struct tevent_req *subreq)
        return;
 
 retry:
-       if (state->packet != NULL) {
-               free_packet(state->packet);
-               state->packet = NULL;
-       }
-       state->socket_req = recvfrom_send(state, state->ev, state->sock,
-                                         state->buf, sizeof(state->buf), 0,
-                                         &state->addr, &state->addr_len);
+       TALLOC_FREE(state->packet);
+       TALLOC_FREE(state->buf);
+       TALLOC_FREE(state->addr);
+
+       state->socket_req = tdgram_recvfrom_send(state, state->ev, state->sock);
        if (tevent_req_nomem(state->socket_req, req)) {
                return;
        }
@@ -486,6 +487,7 @@ retry:
 }
 
 static NTSTATUS sock_packet_read_recv(struct tevent_req *req,
+                                     TALLOC_CTX *mem_ctx,
                                      struct packet_struct **ppacket)
 {
        struct sock_packet_read_state *state = tevent_req_data(
@@ -495,17 +497,17 @@ static NTSTATUS sock_packet_read_recv(struct tevent_req *req,
        if (tevent_req_is_nterror(req, &status)) {
                return status;
        }
-       *ppacket = state->packet;
-       state->packet = NULL;
+       *ppacket = talloc_move(mem_ctx, &state->packet);
        return NT_STATUS_OK;
 }
 
 struct nb_trans_state {
        struct tevent_context *ev;
-       int sock;
+       struct tdgram_context *sock;
        struct nb_packet_reader *reader;
 
-       const struct sockaddr_storage *dst_addr;
+       struct tsocket_address *src_addr;
+       struct tsocket_address *dst_addr;
        uint8_t *buf;
        size_t buflen;
        enum packet_type type;
@@ -518,7 +520,6 @@ struct nb_trans_state {
        struct packet_struct *packet;
 };
 
-static int nb_trans_state_destructor(struct nb_trans_state *s);
 static void nb_trans_got_reader(struct tevent_req *subreq);
 static void nb_trans_done(struct tevent_req *subreq);
 static void nb_trans_sent(struct tevent_req *subreq);
@@ -527,8 +528,8 @@ static void nb_trans_send_next(struct tevent_req *subreq);
 static struct tevent_req *nb_trans_send(
        TALLOC_CTX *mem_ctx,
        struct tevent_context *ev,
-       const struct sockaddr_storage *my_addr,
-       const struct sockaddr_storage *dst_addr,
+       const struct sockaddr_storage *_my_addr,
+       const struct sockaddr_storage *_dst_addr,
        bool bcast,
        uint8_t *buf, size_t buflen,
        enum packet_type type, int trn_id,
@@ -536,16 +537,21 @@ static struct tevent_req *nb_trans_send(
                          void *private_data),
        void *private_data)
 {
+       const struct sockaddr *my_addr =
+               discard_const_p(const struct sockaddr, _my_addr);
+       size_t my_addr_len = sizeof(*_my_addr);
+       const struct sockaddr *dst_addr =
+               discard_const_p(const struct sockaddr, _dst_addr);
+       size_t dst_addr_len = sizeof(*_dst_addr);
        struct tevent_req *req, *subreq;
        struct nb_trans_state *state;
+       int ret;
 
        req = tevent_req_create(mem_ctx, &state, struct nb_trans_state);
        if (req == NULL) {
                return NULL;
        }
-       talloc_set_destructor(state, nb_trans_state_destructor);
        state->ev = ev;
-       state->dst_addr = dst_addr;
        state->buf = buf;
        state->buflen = buflen;
        state->type = type;
@@ -553,15 +559,27 @@ static struct tevent_req *nb_trans_send(
        state->validator = validator;
        state->private_data = private_data;
 
-       state->sock = open_socket_in(SOCK_DGRAM, 0, 3, my_addr, True);
-       if (state->sock == -1) {
+       ret = tsocket_address_bsd_from_sockaddr(state,
+                                               my_addr, my_addr_len,
+                                               &state->src_addr);
+       if (ret == -1) {
                tevent_req_nterror(req, map_nt_error_from_unix(errno));
-               DEBUG(10, ("open_socket_in failed: %s\n", strerror(errno)));
                return tevent_req_post(req, ev);
        }
 
-       if (bcast) {
-               set_socket_options(state->sock,"SO_BROADCAST");
+       ret = tsocket_address_bsd_from_sockaddr(state,
+                                               dst_addr, dst_addr_len,
+                                               &state->dst_addr);
+       if (ret == -1) {
+               tevent_req_nterror(req, map_nt_error_from_unix(errno));
+               return tevent_req_post(req, ev);
+       }
+
+       ret = tdgram_inet_udp_broadcast_socket(state->src_addr, state,
+                                              &state->sock);
+       if (ret == -1) {
+               tevent_req_nterror(req, map_nt_error_from_unix(errno));
+               return tevent_req_post(req, ev);
        }
 
        subreq = nb_packet_reader_send(state, ev, type, state->trn_id, NULL);
@@ -572,19 +590,6 @@ static struct tevent_req *nb_trans_send(
        return req;
 }
 
-static int nb_trans_state_destructor(struct nb_trans_state *s)
-{
-       if (s->sock != -1) {
-               close(s->sock);
-               s->sock = -1;
-       }
-       if (s->packet != NULL) {
-               free_packet(s->packet);
-               s->packet = NULL;
-       }
-       return 0;
-}
-
 static void nb_trans_got_reader(struct tevent_req *subreq)
 {
        struct tevent_req *req = tevent_req_callback_data(
@@ -610,8 +615,10 @@ static void nb_trans_got_reader(struct tevent_req *subreq)
        }
        tevent_req_set_callback(subreq, nb_trans_done, req);
 
-       subreq = sendto_send(state, state->ev, state->sock,
-                            state->buf, state->buflen, 0, state->dst_addr);
+       subreq = tdgram_sendto_send(state, state->ev,
+                                   state->sock,
+                                   state->buf, state->buflen,
+                                   state->dst_addr);
        if (tevent_req_nomem(subreq, req)) {
                return;
        }
@@ -627,7 +634,7 @@ static void nb_trans_sent(struct tevent_req *subreq)
        ssize_t sent;
        int err;
 
-       sent = sendto_recv(subreq, &err);
+       sent = tdgram_sendto_recv(subreq, &err);
        TALLOC_FREE(subreq);
        if (sent == -1) {
                DEBUG(10, ("sendto failed: %s\n", strerror(err)));
@@ -656,8 +663,10 @@ static void nb_trans_send_next(struct tevent_req *subreq)
                tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
                return;
        }
-       subreq = sendto_send(state, state->ev, state->sock,
-                            state->buf, state->buflen, 0, state->dst_addr);
+       subreq = tdgram_sendto_send(state, state->ev,
+                                   state->sock,
+                                   state->buf, state->buflen,
+                                   state->dst_addr);
        if (tevent_req_nomem(subreq, req)) {
                return;
        }
@@ -672,7 +681,7 @@ static void nb_trans_done(struct tevent_req *subreq)
                req, struct nb_trans_state);
        NTSTATUS status;
 
-       status = sock_packet_read_recv(subreq, &state->packet);
+       status = sock_packet_read_recv(subreq, state, &state->packet);
        TALLOC_FREE(subreq);
        if (tevent_req_nterror(req, status)) {
                return;
@@ -680,7 +689,7 @@ static void nb_trans_done(struct tevent_req *subreq)
        tevent_req_done(req);
 }
 
-static NTSTATUS nb_trans_recv(struct tevent_req *req,
+static NTSTATUS nb_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
                              struct packet_struct **ppacket)
 {
        struct nb_trans_state *state = tevent_req_data(
@@ -690,8 +699,7 @@ static NTSTATUS nb_trans_recv(struct tevent_req *req,
        if (tevent_req_is_nterror(req, &status)) {
                return status;
        }
-       *ppacket = state->packet;
-       state->packet = NULL;
+       *ppacket = talloc_move(mem_ctx, &state->packet);
        return NT_STATUS_OK;
 }
 
@@ -708,8 +716,6 @@ struct node_status_query_state {
        struct packet_struct *packet;
 };
 
-static int node_status_query_state_destructor(
-       struct node_status_query_state *s);
 static bool node_status_query_validator(struct packet_struct *p,
                                        void *private_data);
 static void node_status_query_done(struct tevent_req *subreq);
@@ -730,7 +736,6 @@ struct tevent_req *node_status_query_send(TALLOC_CTX *mem_ctx,
        if (req == NULL) {
                return NULL;
        }
-       talloc_set_destructor(state, node_status_query_state_destructor);
 
        if (addr->ss_family != AF_INET) {
                /* Can't do node status to IPv6 */
@@ -805,16 +810,6 @@ static bool node_status_query_validator(struct packet_struct *p,
        return true;
 }
 
-static int node_status_query_state_destructor(
-       struct node_status_query_state *s)
-{
-       if (s->packet != NULL) {
-               free_packet(s->packet);
-               s->packet = NULL;
-       }
-       return 0;
-}
-
 static void node_status_query_done(struct tevent_req *subreq)
 {
        struct tevent_req *req = tevent_req_callback_data(
@@ -823,7 +818,7 @@ static void node_status_query_done(struct tevent_req *subreq)
                req, struct node_status_query_state);
        NTSTATUS status;
 
-       status = nb_trans_recv(subreq, &state->packet);
+       status = nb_trans_recv(subreq, state, &state->packet);
        TALLOC_FREE(subreq);
        if (tevent_req_nterror(req, status)) {
                return;
@@ -885,6 +880,42 @@ NTSTATUS node_status_query(TALLOC_CTX *mem_ctx, struct nmb_name *name,
        return status;
 }
 
+static bool name_status_lmhosts(const struct sockaddr_storage *paddr,
+                               int qname_type, fstring pname)
+{
+       FILE *f;
+       char *name;
+       int name_type;
+       struct sockaddr_storage addr;
+
+       if (paddr->ss_family != AF_INET) {
+               return false;
+       }
+
+       f = startlmhosts(get_dyn_LMHOSTSFILE());
+       if (f == NULL) {
+               return false;
+       }
+
+       while (getlmhostsent(talloc_tos(), f, &name, &name_type, &addr)) {
+               if (addr.ss_family != AF_INET) {
+                       continue;
+               }
+               if (name_type != qname_type) {
+                       continue;
+               }
+               if (memcmp(&((const struct sockaddr_in *)paddr)->sin_addr,
+                          &((const struct sockaddr_in *)&addr)->sin_addr,
+                          sizeof(struct in_addr)) == 0) {
+                       fstrcpy(pname, name);
+                       endlmhosts(f);
+                       return true;
+               }
+       }
+       endlmhosts(f);
+       return false;
+}
+
 /****************************************************************************
  Find the first type XX name in a node status reply - used for finding
  a servers name given its IP. Return the matched name in *name.
@@ -926,6 +957,13 @@ bool name_status_find(const char *q_name,
                return false;
        }
 
+       result = name_status_lmhosts(to_ss, type, name);
+       if (result) {
+               DBG_DEBUG("Found name %s in lmhosts\n", name);
+               namecache_status_store(q_name, q_type, type, to_ss, name);
+               return true;
+       }
+
        set_socket_addr_v4(&ss);
 
        /* W2K PDC's seem not to respond to '*'#0. JRA */
@@ -1055,7 +1093,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;
 
@@ -1426,7 +1464,7 @@ static void name_query_done(struct tevent_req *subreq)
        NTSTATUS status;
        struct packet_struct *p = NULL;
 
-       status = nb_trans_recv(subreq, &p);
+       status = nb_trans_recv(subreq, state, &p);
        TALLOC_FREE(subreq);
        if (tevent_req_nterror(req, status)) {
                return;
@@ -1435,13 +1473,6 @@ static void name_query_done(struct tevent_req *subreq)
                tevent_req_nterror(req, state->validate_error);
                return;
        }
-       if (p != NULL) {
-               /*
-                * Free the packet here, we've collected the response in the
-                * validator
-                */
-               free_packet(p);
-       }
        tevent_req_done(req);
 }
 
@@ -1636,7 +1667,6 @@ 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_oom(req);
                return tevent_req_post(req, ev);
        }
        tevent_req_set_callback(subreq, name_queries_done, req);
@@ -1719,7 +1749,6 @@ 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_oom(req);
                return;
        }
        state->subreqs[state->num_sent] = subreq;
@@ -1956,7 +1985,6 @@ static struct tevent_req *query_wins_list_send(
        }
        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);
@@ -2003,7 +2031,6 @@ static void query_wins_list_done(struct tevent_req *subreq)
        }
        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);
@@ -2243,60 +2270,13 @@ fail:
        return status;
 }
 
-/********************************************************
- Resolve via "lmhosts" method.
-*********************************************************/
-
-static NTSTATUS resolve_lmhosts(const char *name, int name_type,
-                               struct ip_service **return_iplist,
-                               int *return_count)
-{
-       /*
-        * "lmhosts" means parse the local lmhosts file.
-        */
-       struct sockaddr_storage *ss_list;
-       NTSTATUS status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
-       TALLOC_CTX *ctx = NULL;
-
-       *return_iplist = NULL;
-       *return_count = 0;
-
-       DEBUG(3,("resolve_lmhosts: "
-               "Attempting lmhosts lookup for name %s<0x%x>\n",
-               name, name_type));
-
-       ctx = talloc_init("resolve_lmhosts");
-       if (!ctx) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       status = resolve_lmhosts_file_as_sockaddr(get_dyn_LMHOSTSFILE(), 
-                                                 name, name_type, 
-                                                 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 status;
-}
-
-
 /********************************************************
  Resolve via "hosts" method.
 *********************************************************/
 
 static NTSTATUS resolve_hosts(const char *name, int name_type,
-                             struct ip_service **return_iplist,
+                             TALLOC_CTX *mem_ctx,
+                             struct sockaddr_storage **return_iplist,
                              int *return_count)
 {
        /*
@@ -2307,7 +2287,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 "
@@ -2332,32 +2311,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,
@@ -2384,16 +2337,15 @@ static NTSTATUS resolve_hosts(const char *name, int name_type,
 
                *return_count += 1;
 
-               *return_iplist = SMB_REALLOC_ARRAY(*return_iplist,
-                                               struct ip_service,
-                                               *return_count);
+               *return_iplist = talloc_realloc(
+                       mem_ctx, *return_iplist, struct sockaddr_storage,
+                       *return_count);
                if (!*return_iplist) {
                        DEBUG(3,("resolve_hosts: malloc fail !\n"));
                        freeaddrinfo(ailist);
                        return NT_STATUS_NO_MEMORY;
                }
-               (*return_iplist)[i].ss = ss;
-               (*return_iplist)[i].port = PORT_NONE;
+               (*return_iplist)[i] = ss;
                i++;
        }
        if (ailist) {
@@ -2424,7 +2376,6 @@ static NTSTATUS resolve_ads(const char *name,
        struct dns_rr_srv       *dcs = NULL;
        int                     numdcs = 0;
        int                     numaddrs = 0;
-       const char *dns_hosts_file;
 
        if ((name_type != 0x1c) && (name_type != KDC_NAME_TYPE) &&
            (name_type != 0x1b)) {
@@ -2437,28 +2388,32 @@ static NTSTATUS resolve_ads(const char *name,
        }
 
        /* The DNS code needs fixing to find IPv6 addresses... JRA. */
-
-       dns_hosts_file = lp_parm_const_string(-1, "resolv", "host file", NULL);
        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, dns_hosts_file,
-                                                  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, dns_hosts_file,
-                                                  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, dns_hosts_file,
-                                                   name, sitename, &dcs,
+                       status = ads_dns_query_kdcs(ctx,
+                                                   name,
+                                                   sitename,
+                                                   &dcs,
                                                    &numdcs);
                        break;
                default:
@@ -2471,6 +2426,13 @@ static NTSTATUS resolve_ads(const char *name,
                return status;
        }
 
+       if (numdcs == 0) {
+               *return_iplist = NULL;
+               *return_count = 0;
+               talloc_destroy(ctx);
+               return NT_STATUS_OK;
+       }
+
        for (i=0;i<numdcs;i++) {
                if (!dcs[i].ss_s) {
                        numaddrs += 1;
@@ -2547,7 +2509,7 @@ static NTSTATUS resolve_ads(const char *name,
                                freeaddrinfo(res);
                        }
                } else {
-                       /* use all the IP addresses from the SRV sresponse */
+                       /* use all the IP addresses from the SRV response */
                        int j;
                        for (j = 0; j < dcs[i].num_ips; j++) {
                                (*return_iplist)[*return_count].port = dcs[i].port;
@@ -2568,6 +2530,38 @@ static NTSTATUS resolve_ads(const char *name,
        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;
+
+       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;
+
+       return result;
+}
+
 /*******************************************************************
  Internal interface to resolve a name into an IP address.
  Use this function if the string is either an IP address, DNS
@@ -2649,16 +2643,36 @@ NTSTATUS internal_resolve_name(const char *name,
                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) {
+                       TALLOC_FREE(frame);
+                       return NT_STATUS_NO_MEMORY;
+               }
+       }
+
        /* iterate through the name resolution backends */
 
-       frame = talloc_stackframe();
        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,
+                       struct sockaddr_storage *ss_list;
+                       status = resolve_hosts(name, name_type,
+                                              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, "kdc")) {
@@ -2680,13 +2694,20 @@ NTSTATUS internal_resolve_name(const char *name,
                        if (NT_STATUS_IS_OK(status)) {
                                goto done;
                        }
-               } else if(strequal( tok, "lmhosts")) {
-                       status = resolve_lmhosts(name, name_type,
-                                                return_iplist, return_count);
+               } else if (strequal(tok, "lmhosts")) {
+                       struct sockaddr_storage *ss_list;
+                       status = resolve_lmhosts_file_as_sockaddr(
+                               get_dyn_LMHOSTSFILE(), name, name_type,
+                               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, "wins")) {
+               } else if (strequal(tok, "wins")) {
                        /* don't resolve 1D via WINS */
                        struct sockaddr_storage *ss_list;
                        if (name_type != 0x1D) {
@@ -2703,7 +2724,7 @@ NTSTATUS internal_resolve_name(const char *name,
                                        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(),
@@ -2794,12 +2815,15 @@ bool resolve_name(const char *name,
        char *sitename = NULL;
        int count = 0;
        NTSTATUS status;
+       TALLOC_CTX *frame = NULL;
 
        if (is_ipaddress(name)) {
                return interpret_string_addr(return_ss, name, AI_NUMERICHOST);
        }
 
-       sitename = sitename_fetch(lp_realm()); /* wild guess */
+       frame = talloc_stackframe();
+
+       sitename = sitename_fetch(frame, lp_realm()); /* wild guess */
 
        status = internal_resolve_name(name, name_type, sitename,
                                       &ss_list, &count,
@@ -2814,7 +2838,7 @@ bool resolve_name(const char *name,
                                                (ss_list[i].ss.ss_family == AF_INET)) {
                                        *return_ss = ss_list[i].ss;
                                        SAFE_FREE(ss_list);
-                                       SAFE_FREE(sitename);
+                                       TALLOC_FREE(frame);
                                        return True;
                                }
                        }
@@ -2826,14 +2850,14 @@ bool resolve_name(const char *name,
                            !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(frame);
                                return True;
                        }
                }
        }
 
        SAFE_FREE(ss_list);
-       SAFE_FREE(sitename);
+       TALLOC_FREE(frame);
        return False;
 }
 
@@ -2873,12 +2897,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;
@@ -2976,6 +3000,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;
                }
        }
@@ -3023,15 +3048,12 @@ static NTSTATUS get_dc_list(const char *domain,
        bool done_auto_lookup = false;
        int auto_count = 0;
        NTSTATUS status;
-       TALLOC_CTX *ctx = talloc_init("get_dc_list");
+       TALLOC_CTX *ctx = talloc_stackframe();
+       int auto_name_type = 0x1C;
 
        *ip_list = NULL;
        *count = 0;
 
-       if (!ctx) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
        *ordered = False;
 
        /* if we are restricted to solely using DNS for looking
@@ -3064,41 +3086,29 @@ static NTSTATUS get_dc_list(const char *domain,
                   are already sorted by priority and weight */
                *ordered = true;
                resolve_order = kdc_order;
-       }
-       if (!resolve_order) {
-               status = NT_STATUS_NO_MEMORY;
-               goto out;
+               auto_name_type = KDC_NAME_TYPE;
        }
 
        /* 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;
        }
 
-       /* if we are starting from scratch, just lookup DOMAIN<0x1c> */
-
-       if (!*pserver ) {
-               DEBUG(10,("get_dc_list: no preferred domain controllers.\n"));
-               status = internal_resolve_name(domain, 0x1C, sitename, ip_list,
-                                            count, resolve_order);
-               goto out;
-       }
-
        DEBUG(3,("get_dc_list: preferred server list: \"%s\"\n", pserver ));
 
        /*
@@ -3111,7 +3121,8 @@ static NTSTATUS get_dc_list(const char *domain,
        p = pserver;
        while (next_token_talloc(ctx, &p, &name, LIST_SEP)) {
                if (!done_auto_lookup && strequal(name, "*")) {
-                       status = internal_resolve_name(domain, 0x1C, sitename,
+                       status = internal_resolve_name(domain, auto_name_type,
+                                                      sitename,
                                                       &auto_ip_list,
                                                       &auto_count,
                                                       resolve_order);
@@ -3135,7 +3146,8 @@ static NTSTATUS get_dc_list(const char *domain,
                        status = NT_STATUS_NO_LOGON_SERVERS;
                        goto out;
                }
-               status = internal_resolve_name(domain, 0x1C, sitename, ip_list,
+               status = internal_resolve_name(domain, auto_name_type,
+                                              sitename, ip_list,
                                             count, resolve_order);
                goto out;
        }
@@ -3156,7 +3168,7 @@ static NTSTATUS get_dc_list(const char *domain,
                        next_token_talloc(ctx, &p, &name, LIST_SEP)) {
                struct sockaddr_storage name_ss;
 
-               /* copy any addersses from the auto lookup */
+               /* copy any addresses from the auto lookup */
 
                if (strequal(name, "*")) {
                        for (j=0; j<auto_count; j++) {
@@ -3187,13 +3199,19 @@ static NTSTATUS get_dc_list(const char *domain,
                /* added support for address:port syntax for ads
                 * (not that I think anyone will ever run the LDAP
                 * server in an AD domain on something other than
-                * port 389 */
+                * port 389
+                * However, the port should not be used for kerberos
+                */
 
-               port = (lp_security() == SEC_ADS) ? LDAP_PORT : PORT_NONE;
+               port = (lookup_type == DC_ADS_ONLY) ? LDAP_PORT :
+                       ((lookup_type == DC_KDC_ONLY) ? DEFAULT_KRB5_PORT :
+                        PORT_NONE);
                if ((port_str=strchr(name, ':')) != NULL) {
                        *port_str = '\0';
-                       port_str++;
-                       port = atoi(port_str);
+                       if (lookup_type != DC_KDC_ONLY) {
+                               port_str++;
+                               port = atoi(port_str);
+                       }
                }
 
                /* explicit lookup; resolve_name() will