From: Volker Lendecke Date: Wed, 27 May 2026 08:44:58 +0000 (+0200) Subject: addns: Add ads_dns_lookup_in() X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=afbf58a44bbaa3cfcb7aeb31290c53096bb4ccdb;p=thirdparty%2Fsamba.git addns: Add ads_dns_lookup_in() The next patches will convert all users of ads_dns_lookup_a[aaaa]. Signed-off-by: Volker Lendecke Reviewed-by: Anoop C S --- diff --git a/lib/addns/dnsquery.c b/lib/addns/dnsquery.c index e22461c0915..5fb70d31ff9 100644 --- a/lib/addns/dnsquery.c +++ b/lib/addns/dnsquery.c @@ -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; +} diff --git a/lib/addns/dnsquery.h b/lib/addns/dnsquery.h index 51f6b8ff87b..cb300b19a80 100644 --- a/lib/addns/dnsquery.h +++ b/lib/addns/dnsquery.h @@ -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__ */