summaryrefslogtreecommitdiff
path: root/libcli
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2011-04-26 09:49:08 +1000
committerAndrew Bartlett <abartlet@samba.org>2011-04-26 17:16:34 +1000
commitc18954775e53a0f4dec4e36234dc45559055f96d (patch)
tree1a77efa4d9a08da2e90c7e147552cd11bca44b68 /libcli
parent3a88d49d12fe6c74dffe3e8d82235c71511cc07c (diff)
downloadsamba-c18954775e53a0f4dec4e36234dc45559055f96d.tar.gz
samba-c18954775e53a0f4dec4e36234dc45559055f96d.tar.bz2
samba-c18954775e53a0f4dec4e36234dc45559055f96d.zip
libcli/dns Improve dns_hosts_file, using Samba3's struct dns_rr_srv
By reworking the 'fake DNS' file to use struct dns_rr_srv it should be possible to emulate that resolver layer as well as the Samba4 sockaddr_storage* based layer. This will then give us a common DNS emulation for 'make test'. Andrew Bartlett
Diffstat (limited to 'libcli')
-rw-r--r--libcli/dns/dns.h68
-rw-r--r--libcli/dns/dns_hosts_file.c (renamed from libcli/nbt/dns_hosts_file.c)212
-rw-r--r--libcli/nbt/wscript_build4
3 files changed, 230 insertions, 54 deletions
diff --git a/libcli/dns/dns.h b/libcli/dns/dns.h
new file mode 100644
index 0000000000..01aa6c4e6c
--- /dev/null
+++ b/libcli/dns/dns.h
@@ -0,0 +1,68 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Internal DNS query structures
+ * Copyright (C) Gerald Carter 2006.
+ * Copyright (C) Andrew Bartlett 2011
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* DNS query section in replies */
+
+struct dns_query {
+ const char *hostname;
+ uint16_t type;
+ uint16_t in_class;
+};
+
+/* DNS RR record in reply */
+
+struct dns_rr {
+ const char *hostname;
+ uint16_t type;
+ uint16_t in_class;
+ uint32_t ttl;
+ uint16_t rdatalen;
+ uint8_t *rdata;
+};
+
+/* SRV records */
+
+struct dns_rr_srv {
+ const char *hostname;
+ uint16_t priority;
+ uint16_t weight;
+ uint16_t port;
+ size_t num_ips;
+ struct sockaddr_storage *ss_s; /* support multi-homed hosts */
+};
+
+/* NS records */
+
+struct dns_rr_ns {
+ const char *hostname;
+ struct sockaddr_storage ss;
+};
+
+NTSTATUS resolve_dns_hosts_file_as_sockaddr(const char *dns_hosts_file,
+ const char *name, bool srv_lookup,
+ TALLOC_CTX *mem_ctx,
+ struct sockaddr_storage **return_iplist,
+ int *return_count);
+
+NTSTATUS resolve_dns_hosts_file_as_dns_rr(const char *dns_hosts_file,
+ const char *name, bool srv_lookup,
+ TALLOC_CTX *mem_ctx,
+ struct dns_rr_srv **return_rr,
+ int *return_count);
diff --git a/libcli/nbt/dns_hosts_file.c b/libcli/dns/dns_hosts_file.c
index 801393650e..94d1d9704a 100644
--- a/libcli/nbt/dns_hosts_file.c
+++ b/libcli/dns/dns_hosts_file.c
@@ -5,7 +5,7 @@
Copyright (C) Andrew Tridgell 1994-1998
Copyright (C) Jeremy Allison 2007
- Copyright (C) Andrew Bartlett 2009.
+ Copyright (C) Andrew Bartlett 2009-2011
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -29,6 +29,11 @@
#include "system/filesys.h"
#include "system/network.h"
#include "libcli/nbt/libnbt.h"
+#include "libcli/dns/dns.h"
+
+#ifdef strcasecmp
+#undef strcasecmp
+#endif
/********************************************************
Start parsing the dns_hosts_file file.
@@ -51,7 +56,7 @@ static XFILE *startdns_hosts_file(const char *fname)
*********************************************************/
static bool getdns_hosts_fileent(TALLOC_CTX *ctx, XFILE *fp, char **pp_name, char **pp_name_type,
- char **pp_next_name,
+ char **pp_next_name,
struct sockaddr_storage *pss, uint32_t *p_port)
{
char line[1024];
@@ -176,12 +181,12 @@ static void enddns_hosts_file(XFILE *fp)
Resolve via "dns_hosts" method.
*********************************************************/
-static NTSTATUS resolve_dns_hosts_file_as_sockaddr_recurse(const char *dns_hosts_file,
- const char *name, bool srv_lookup,
- int level, uint32_t port,
- TALLOC_CTX *mem_ctx,
- struct sockaddr_storage **return_iplist,
- int *return_count)
+static NTSTATUS resolve_dns_hosts_file_as_dns_rr_recurse(const char *dns_hosts_file,
+ const char *name, bool srv_lookup,
+ int level, uint32_t port,
+ TALLOC_CTX *mem_ctx,
+ struct dns_rr_srv **return_rr,
+ int *return_count)
{
/*
* "dns_hosts" means parse the local dns_hosts file.
@@ -196,18 +201,21 @@ static NTSTATUS resolve_dns_hosts_file_as_sockaddr_recurse(const char *dns_hosts
NTSTATUS status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
TALLOC_CTX *ctx = NULL;
TALLOC_CTX *ip_list_ctx = NULL;
+ struct dns_rr_srv *rr = NULL;
+
+ *return_rr = NULL;
/* Don't recurse forever, even on our own flat files */
if (level > 11) {
-
+ DEBUG(0, ("resolve_dns_hosts_file recursion limit reached looking up %s!\n", name));
+ return status;
}
- *return_iplist = NULL;
*return_count = 0;
- DEBUG(3,("resolve_dns_hosts: "
- "Attempting dns_hosts lookup for name %s\n",
- name));
+ DEBUG(3,("resolve_dns_hosts: (%d) "
+ "Attempting %s dns_hosts lookup for name %s\n",
+ level, srv_lookup ? "SRV" : "A", name));
fp = startdns_hosts_file(dns_hosts_file);
@@ -229,79 +237,179 @@ static NTSTATUS resolve_dns_hosts_file_as_sockaddr_recurse(const char *dns_hosts
while (getdns_hosts_fileent(ctx, fp, &host_name, &name_type, &next_name, &return_ss, &srv_port)) {
if (!strequal(name, host_name)) {
- TALLOC_FREE(ctx);
- ctx = talloc_new(mem_ctx);
- if (!ctx) {
- enddns_hosts_file(fp);
- return NT_STATUS_NO_MEMORY;
- }
-
- continue;
- }
-
- if (srv_lookup) {
+ /* continue at the bottom of the loop */
+ } else if (srv_lookup) {
if (strcasecmp(name_type, "SRV") == 0) {
+ NTSTATUS status_recurse;
+ struct dns_rr_srv *tmp_rr;
+ int tmp_count = 0;
/* we only accept one host name per SRV entry */
- enddns_hosts_file(fp);
- status = resolve_dns_hosts_file_as_sockaddr_recurse(dns_hosts_file, next_name,
- false,
- level + 1, srv_port,
- mem_ctx, return_iplist,
- return_count);
- talloc_free(ip_list_ctx);
- return status;
- } else {
- continue;
+ status_recurse
+ = resolve_dns_hosts_file_as_dns_rr_recurse(dns_hosts_file, next_name,
+ false,
+ level + 1, srv_port,
+ ip_list_ctx, &tmp_rr,
+ &tmp_count);
+ if (NT_STATUS_EQUAL(status_recurse, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+ /* Don't fail on a dangling SRV record */
+ } else if (!NT_STATUS_IS_OK(status_recurse)) {
+ enddns_hosts_file(fp);
+ talloc_free(ip_list_ctx);
+ return status_recurse;
+ } else if (tmp_count != 1) {
+ status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ } else {
+ status = status_recurse;
+ rr = talloc_realloc(ip_list_ctx, rr, struct dns_rr_srv, (*return_count) + 1);
+ if (!rr) {
+ enddns_hosts_file(fp);
+ return NT_STATUS_NO_MEMORY;
+ }
+ talloc_steal(rr, tmp_rr);
+ rr[*return_count] = *tmp_rr;
+ *return_count = (*return_count) + 1;
+ }
}
} else if (strcasecmp(name_type, "CNAME") == 0) {
/* we only accept one host name per CNAME */
enddns_hosts_file(fp);
- status = resolve_dns_hosts_file_as_sockaddr_recurse(dns_hosts_file, next_name, false,
- level + 1, port,
- mem_ctx, return_iplist, return_count);
+ status = resolve_dns_hosts_file_as_dns_rr_recurse(dns_hosts_file, next_name, false,
+ level + 1, port,
+ mem_ctx, return_rr, return_count);
talloc_free(ip_list_ctx);
return status;
} else if (strcasecmp(name_type, "A") == 0) {
+ if (*return_count == 0) {
+ /* We are happy to keep looking for other possible A record matches */
+ rr = talloc_zero(ip_list_ctx,
+ struct dns_rr_srv);
+
+ if (rr == NULL) {
+ TALLOC_FREE(ctx);
+ enddns_hosts_file(fp);
+ DEBUG(3,("resolve_dns_hosts: talloc_realloc fail !\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ rr->hostname = talloc_strdup(rr, host_name);
+
+ if (rr->hostname == NULL) {
+ TALLOC_FREE(ctx);
+ enddns_hosts_file(fp);
+ DEBUG(3,("resolve_dns_hosts: talloc_realloc fail !\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+ rr->port = port;
+
+ *return_count = 1;
+ }
+
/* Set the specified port (possibly from a SRV lookup) into the structure we return */
set_sockaddr_port((struct sockaddr *)&return_ss, port);
/* We are happy to keep looking for other possible A record matches */
- *return_iplist = talloc_realloc(ip_list_ctx, (*return_iplist),
- struct sockaddr_storage,
- (*return_count)+1);
+ rr->ss_s = talloc_realloc(rr, rr->ss_s,
+ struct sockaddr_storage,
+ rr->num_ips + 1);
- if ((*return_iplist) == NULL) {
+ if (rr->ss_s == NULL) {
TALLOC_FREE(ctx);
enddns_hosts_file(fp);
DEBUG(3,("resolve_dns_hosts: talloc_realloc fail !\n"));
return NT_STATUS_NO_MEMORY;
}
-
- (*return_iplist)[*return_count] = return_ss;
- *return_count += 1;
-
+
+ rr->ss_s[rr->num_ips] = return_ss;
+ rr->num_ips += 1;
+
/* we found something */
status = NT_STATUS_OK;
}
+
+ TALLOC_FREE(ctx);
+ ctx = talloc_new(mem_ctx);
+ if (!ctx) {
+ enddns_hosts_file(fp);
+ return NT_STATUS_NO_MEMORY;
+ }
}
- talloc_steal(mem_ctx, *return_iplist);
+ *return_rr = talloc_steal(mem_ctx, rr);
TALLOC_FREE(ip_list_ctx);
enddns_hosts_file(fp);
return status;
}
/********************************************************
- Resolve via "dns_hosts" method.
+ Resolve via "dns_hosts_file" method, returning a list of sockaddr_storage values
*********************************************************/
-NTSTATUS resolve_dns_hosts_file_as_sockaddr(const char *dns_hosts_file,
+NTSTATUS resolve_dns_hosts_file_as_sockaddr(const char *dns_hosts_file,
const char *name, bool srv_lookup,
- TALLOC_CTX *mem_ctx,
+ TALLOC_CTX *mem_ctx,
struct sockaddr_storage **return_iplist,
int *return_count)
{
- return resolve_dns_hosts_file_as_sockaddr_recurse(dns_hosts_file, name, srv_lookup,
- 0, 0,
- mem_ctx, return_iplist, return_count);
+ NTSTATUS status;
+ struct dns_rr_srv *dns_rr = NULL;
+ int i, j, rr_count = 0;
+
+ *return_iplist = NULL;
+ *return_count = 0;
+
+ status = resolve_dns_hosts_file_as_dns_rr_recurse(dns_hosts_file, name, srv_lookup,
+ 0, 0,
+ mem_ctx, &dns_rr, &rr_count);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(3,("resolve_dns_hosts (sockaddr): "
+ "failed to obtain %s result records for for name %s: %s\n",
+ srv_lookup ? "SRV" : "A", name, nt_errstr(status)));
+ return status;
+ }
+
+ for (i=0; i < rr_count; i++) {
+ *return_iplist = talloc_realloc(mem_ctx, *return_iplist, struct sockaddr_storage, *return_count + dns_rr[i].num_ips);
+ if (!*return_iplist) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ for (j=0; j < dns_rr[i].num_ips; j++) {
+ (*return_iplist)[*return_count] = dns_rr[i].ss_s[j];
+ *return_count = *return_count + 1;
+ }
+ }
+ DEBUG(3,("resolve_dns_hosts (sockaddr): "
+ "Found %d results for for name %s\n",
+ *return_count, name));
+
+ return NT_STATUS_OK;
+}
+
+/********************************************************
+ Resolve via "dns_hosts_file" method, returning struct dns_rr_srv
+*********************************************************/
+
+NTSTATUS resolve_dns_hosts_file_as_dns_rr(const char *dns_hosts_file,
+ const char *name, bool srv_lookup,
+ TALLOC_CTX *mem_ctx,
+ struct dns_rr_srv **return_rr,
+ int *return_count)
+{
+ NTSTATUS status;
+ *return_rr = NULL;
+ *return_count = 0;
+
+ status = resolve_dns_hosts_file_as_dns_rr_recurse(dns_hosts_file, name, srv_lookup,
+ 0, 0,
+ mem_ctx, return_rr, return_count);
+
+ if (NT_STATUS_IS_OK(status)) {
+ DEBUG(3,("resolve_dns_hosts (dns_rr): "
+ "Found %d %s result records for for name %s\n",
+ *return_count, srv_lookup ? "SRV" : "A", name));
+ } else {
+ DEBUG(3,("resolve_dns_hosts (dns_rr): "
+ "failed to obtain %s result records for for name %s: %s\n",
+ srv_lookup ? "SRV" : "A", name, nt_errstr(status)));
+ }
+ return status;
}
diff --git a/libcli/nbt/wscript_build b/libcli/nbt/wscript_build
index 6f7a1745b7..07d8c51b1f 100644
--- a/libcli/nbt/wscript_build
+++ b/libcli/nbt/wscript_build
@@ -7,13 +7,13 @@ bld.SAMBA_SUBSYSTEM('NDR_NBT_BUF',
)
bld.SAMBA_SUBSYSTEM('lmhosts',
- source='lmhosts.c',
+ source='lmhosts.c ../dns/dns_hosts_file.c',
deps='replace talloc'
)
if bld.env._SAMBA_BUILD_ == 4:
bld.SAMBA_LIBRARY('cli-nbt',
- source='nbtsocket.c namequery.c nameregister.c namerefresh.c namerelease.c dns_hosts_file.c',
+ source='nbtsocket.c namequery.c nameregister.c namerefresh.c namerelease.c',
public_deps='ndr NDR_NBT tevent UTIL_TEVENT NDR_SECURITY samba_socket samba-util lmhosts',
private_library=True
)