addns: Remove support for dns_host_file.
[obnox/samba/samba-obnox.git] / source3 / libsmb / namequery.c
index f2c8d4a2f7d76a9085bf2e8b2926864f05b82a8f..3ee79b68a31a5b178a91a8719a2c4b7cc8219511 100644 (file)
@@ -21,7 +21,7 @@
 #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"
@@ -165,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;
@@ -183,7 +183,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 +199,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 );
 
@@ -216,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);
        }
@@ -867,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;
        }
@@ -1102,7 +1102,7 @@ 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;
 
@@ -1491,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;
        }
@@ -1877,11 +1877,11 @@ NTSTATUS name_resolve_bcast(const char *name,
                        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;
        }
@@ -2071,7 +2071,7 @@ struct tevent_req *resolve_wins_send(TALLOC_CTX *mem_ctx,
        }
 
        /* 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);
        }
@@ -2225,7 +2225,7 @@ NTSTATUS resolve_wins(const char *name,
        struct tevent_req *req;
        NTSTATUS status = NT_STATUS_NO_MEMORY;
 
-       ev = tevent_context_init(talloc_tos());
+       ev = samba_tevent_context_init(talloc_tos());
        if (ev == NULL) {
                goto fail;
        }
@@ -2418,7 +2418,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;
@@ -2436,24 +2436,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:
@@ -2467,8 +2475,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 ) {
@@ -2481,42 +2493,77 @@ 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++;
-               }
-
-               /* 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 */
-
-               if (!is_zero_addr(&r->ss)) {
-                       (*return_count)++;
+                       /* 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;
+                               }
+                       }
                }
        }
 
@@ -2540,10 +2587,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;
@@ -2596,21 +2642,22 @@ 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;
        }
 
        /* 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);
@@ -2755,7 +2802,7 @@ bool resolve_name(const char *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 */
 
        status = internal_resolve_name(name, name_type, sitename,
                                       &ss_list, &count,
@@ -2770,7 +2817,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(sitename);
                                        return True;
                                }
                        }
@@ -2782,14 +2829,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(sitename);
                                return True;
                        }
                }
        }
 
        SAFE_FREE(ss_list);
-       SAFE_FREE(sitename);
+       TALLOC_FREE(sitename);
        return False;
 }
 
@@ -2829,12 +2876,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;
@@ -2919,12 +2966,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) {
@@ -2932,6 +2979,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;
                }
        }
@@ -2965,7 +3013,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;
@@ -2996,27 +3044,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;
@@ -3026,18 +3077,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;
@@ -3237,10 +3288,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;