]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
addns: Add ads_dns_lookup_in()
authorVolker Lendecke <vl@samba.org>
Wed, 27 May 2026 08:44:58 +0000 (10:44 +0200)
committerAnoop C S <anoopcs@samba.org>
Wed, 17 Jun 2026 08:28:32 +0000 (08:28 +0000)
The next patches will convert all users of ads_dns_lookup_a[aaaa].

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Anoop C S <anoopcs@samba.org>
lib/addns/dnsquery.c
lib/addns/dnsquery.h

index e22461c09156c052f2ffdabc7e621fbb60d9a6bf..5fb70d31ff9c8043511f9e9167ede2f0d8a3a060 100644 (file)
@@ -780,3 +780,217 @@ fail:
        return status;
 }
 #endif
+
+/*********************************************************************
+ Async A/AAAA lookup.
+*********************************************************************/
+
+struct ads_dns_lookup_in_state {
+       const char *hostname;
+       struct tevent_req *subreq_a;
+       struct tevent_req *subreq_aaaa;
+       char **names;
+       struct samba_sockaddr *addrs;
+};
+
+static void ads_dns_lookup_in_done(struct tevent_req *subreq);
+
+struct tevent_req *ads_dns_lookup_in_send(TALLOC_CTX *mem_ctx,
+                                         struct tevent_context *ev,
+                                         const char *name)
+{
+       struct tevent_req *req = NULL, *subreq = NULL;
+       struct ads_dns_lookup_in_state *state = NULL;
+
+       req = tevent_req_create(mem_ctx,
+                               &state,
+                               struct ads_dns_lookup_in_state);
+       if (req == NULL) {
+               return NULL;
+       }
+       state->hostname = name;
+
+       subreq = dns_lookup_send(
+               state, ev, NULL, name, DNS_QCLASS_IN, DNS_QTYPE_AAAA);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+       tevent_req_set_callback(subreq, ads_dns_lookup_in_done, req);
+       state->subreq_aaaa = subreq;
+
+       subreq = dns_lookup_send(
+               state, ev, NULL, name, DNS_QCLASS_IN, DNS_QTYPE_A);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+       tevent_req_set_callback(subreq, ads_dns_lookup_in_done, req);
+       state->subreq_a = subreq;
+
+       return req;
+}
+
+static void ads_dns_lookup_in_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(subreq,
+                                                         struct tevent_req);
+       struct ads_dns_lookup_in_state *state = tevent_req_data(
+               req, struct ads_dns_lookup_in_state);
+       int ret;
+       struct dns_name_packet *reply = NULL;
+       size_t num_replies;
+       enum dns_qtype qtype;
+       uint8_t rcode;
+       uint16_t i;
+
+       if (subreq == state->subreq_aaaa) {
+               qtype = DNS_QTYPE_AAAA;
+               state->subreq_aaaa = NULL;
+       } else if (subreq == state->subreq_a) {
+               qtype = DNS_QTYPE_A;
+               state->subreq_a = NULL;
+       } else {
+               tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
+               return;
+       }
+
+       ret = dns_lookup_recv(subreq, state, &reply);
+       TALLOC_FREE(subreq);
+       if (ret != 0) {
+               DBG_INFO("dns_lookup_recv returned %s\n", strerror(ret));
+               goto done;
+       }
+
+       ret = ENOENT;
+
+       rcode = (reply->operation & DNS_RCODE);
+       if (rcode != DNS_RCODE_OK) {
+               DBG_INFO("async DNS %s lookup for %s returned DNS code "
+                        "%" PRIu8 "\n",
+                        qtype == DNS_QTYPE_A ? "A" : "AAAA",
+                        state->hostname,
+                        rcode);
+               goto done;
+       }
+
+       for (i = 0; i < reply->ancount; i++) {
+               struct dns_res_rec *an = &reply->answers[i];
+               struct samba_sockaddr ss = {};
+               bool ok;
+
+               if (an->rr_type != qtype) {
+                       continue;
+               }
+               if (an->name == NULL) {
+                       /* Can this happen? */
+                       continue;
+               }
+               ok = dns_res_rec_get_sockaddr(an, &ss);
+               if (!ok) {
+                       continue;
+               }
+               if (is_zero_addr(&ss.u.ss)) {
+                       continue;
+               }
+
+               num_replies = talloc_array_length(state->addrs);
+
+               /*
+                * Do reallocs without the "tmp" pattern: What we
+                * would leak on realloc failure is cleaned up with
+                * "state".
+                */
+               state->addrs = talloc_realloc(state,
+                                             state->addrs,
+                                             struct samba_sockaddr,
+                                             num_replies + 1);
+               if (tevent_req_nomem(state->addrs, req)) {
+                       return;
+               }
+               state->addrs[num_replies] = ss;
+
+               state->names = talloc_realloc(state,
+                                             state->names,
+                                             char *,
+                                             num_replies + 1);
+               if (tevent_req_nomem(state->names, req)) {
+                       return;
+               }
+
+               state->names[num_replies] = talloc_strdup(state->names,
+                                                         an->name);
+               if (tevent_req_nomem(state->names[num_replies], req)) {
+                       return;
+               }
+       }
+done:
+       if ((state->subreq_aaaa != NULL) || (state->subreq_a != NULL)) {
+               /*
+                * Wait for the other subreq
+                */
+               return;
+       }
+
+       num_replies = talloc_array_length(state->addrs);
+       if (num_replies == 0) {
+               tevent_req_nterror(req, map_nt_error_from_unix_common(ret));
+               return;
+       }
+
+       tevent_req_done(req);
+}
+
+NTSTATUS ads_dns_lookup_in_recv(struct tevent_req *req,
+                               TALLOC_CTX *mem_ctx,
+                               char ***_names,
+                               struct samba_sockaddr **_addrs)
+{
+       struct ads_dns_lookup_in_state *state = tevent_req_data(
+               req, struct ads_dns_lookup_in_state);
+       NTSTATUS status;
+
+       if (tevent_req_is_nterror(req, &status)) {
+               return status;
+       }
+       if (_names != NULL) {
+               *_names = talloc_move(mem_ctx, &state->names);
+       }
+       if (_addrs != NULL) {
+               *_addrs = talloc_move(mem_ctx, &state->addrs);
+       }
+       tevent_req_received(req);
+       return NT_STATUS_OK;
+}
+
+/*********************************************************************
+ Simple wrapper for a QCLASS_IN query
+*********************************************************************/
+
+NTSTATUS ads_dns_lookup_in(TALLOC_CTX *ctx,
+                          const char *name,
+                          char ***_names,
+                          struct samba_sockaddr **_addrs)
+{
+       struct tevent_context *ev;
+       struct tevent_req *req;
+       NTSTATUS status = NT_STATUS_NO_MEMORY;
+
+       ev = samba_tevent_context_init(ctx);
+       if (ev == NULL) {
+               goto fail;
+       }
+       req = ads_dns_lookup_in_send(ev, ev, name);
+       if (req == NULL) {
+               goto fail;
+       }
+       if (!tevent_req_poll_ntstatus(req, ev, &status)) {
+               goto fail;
+       }
+       /*
+        * Synchronous doesn't need to care about the rcode or
+        * a copy of the name_in.
+        */
+       status = ads_dns_lookup_in_recv(req, ctx, _names, _addrs);
+fail:
+       TALLOC_FREE(ev);
+       return status;
+}
index 51f6b8ff87bf4daae0324024a055c8607a805aad..cb300b19a8027e54878e74bcf4d4c1a1d3b8fb66 100644 (file)
@@ -25,6 +25,7 @@
 #include "libcli/dns/dns.h"
 #include "lib/util/util_net.h"
 #include "libcli/util/ntstatus.h"
+#include "librpc/gen_ndr/dns.h"
 
 /* The following definitions come from libads/dns.c  */
 
@@ -81,4 +82,16 @@ NTSTATUS ads_dns_lookup_aaaa(TALLOC_CTX *ctx,
                        struct samba_sockaddr **addrs_out);
 #endif
 
+struct tevent_req *ads_dns_lookup_in_send(TALLOC_CTX *mem_ctx,
+                                         struct tevent_context *ev,
+                                         const char *name);
+NTSTATUS ads_dns_lookup_in_recv(struct tevent_req *req,
+                               TALLOC_CTX *mem_ctx,
+                               char ***_names,
+                               struct samba_sockaddr **_addrs);
+NTSTATUS ads_dns_lookup_in(TALLOC_CTX *ctx,
+                          const char *name,
+                          char ***_names,
+                          struct samba_sockaddr **_addrs);
+
 #endif /* __LIB_ADDNS_DNSQUERY_H__ */