1
0
mirror of https://github.com/samba-team/samba.git synced 2025-08-02 00:22:11 +03:00

s4-resolve: Remove dependency on libroken

Use available native samba resolver functions
This commit is contained in:
Simo Sorce
2012-05-04 23:11:19 -04:00
committed by Alexander Bokovoy
parent a8ee6f2ca5
commit c54fe86a63
4 changed files with 172 additions and 222 deletions

View File

@ -1,12 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
bld.SAMBA_LIBRARY('addns', bld.SAMBA_LIBRARY('addns',
source='dnsrecord.c dnsutils.c dnssock.c dnsgss.c dnsmarshall.c error.c', source='dnsquery.c dnsrecord.c dnsutils.c dnssock.c dnsgss.c dnsmarshall.c error.c',
public_deps='talloc krb5 k5crypto com_err gssapi gssapi_krb5 uuid', public_deps='DNS_HOSTS_FILE samba-util krb5 gssapi_krb5 uuid resolv',
private_library=True, private_library=True,
vars=locals()) vars=locals())
bld.SAMBA_SUBSYSTEM('DNSQUERY',
source='dnsquery.c',
deps='samba-util lmhosts resolv'
)

View File

@ -1007,7 +1007,7 @@ bld.SAMBA3_SUBSYSTEM('LIBEVENTLOG',
bld.SAMBA3_SUBSYSTEM('LIBNMB', bld.SAMBA3_SUBSYSTEM('LIBNMB',
source=LIBNMB_SRC, source=LIBNMB_SRC,
deps='DNSQUERY lmhosts resolv', deps='addns lmhosts resolv',
vars=locals()) vars=locals())
bld.SAMBA3_SUBSYSTEM('SERVICES', bld.SAMBA3_SUBSYSTEM('SERVICES',

View File

@ -39,12 +39,10 @@
#include "librpc/gen_ndr/ndr_nbt.h" #include "librpc/gen_ndr/ndr_nbt.h"
#include "libcli/resolve/resolve.h" #include "libcli/resolve/resolve.h"
#include "lib/util/util_net.h" #include "lib/util/util_net.h"
#include "lib/addns/dnsquery.h"
#ifdef class #include "lib/addns/dns.h"
#undef class #include <arpa/nameser.h>
#endif #include <resolv.h>
#include "heimdal/lib/roken/resolve.h"
struct dns_ex_state { struct dns_ex_state {
bool do_fallback; bool do_fallback;
@ -77,261 +75,223 @@ static int dns_ex_destructor(struct dns_ex_state *state)
return 0; return 0;
} }
static uint32_t count_dns_rr(struct rk_resource_record *head, unsigned record_type)
{
uint32_t count = 0;
struct rk_resource_record *rr;
for (rr=head; rr; rr=rr->next) {
/* we are only interested in the IN class */
if (rr->class != rk_ns_c_in) {
continue;
}
if (rr->type == rk_ns_t_ns) {
/*
* Record that will follow will be related to the NS
* not what we are really interested with.
* It's a good idea not to count them
*/
break;
}
/* we are only interested by requested record */
if (rr->type != record_type) {
continue;
}
switch(record_type) {
case rk_ns_t_srv:
/* verify we actually have a SRV record here */
if (!rr->u.srv) {
continue;
}
/* Verify we got a port */
if (rr->u.srv->port == 0) {
continue;
}
count++;
break;
case rk_ns_t_a:
case rk_ns_t_aaaa:
/* verify we actually have a record here */
if (!rr->u.data) {
continue;
}
count++;
break;
default:
count++;
break;
}
}
return count;
}
struct dns_records_container { struct dns_records_container {
char **list; char **list;
uint32_t count; uint32_t count;
}; };
static char* rr_to_string(TALLOC_CTX *mem_ctx, static int reply_to_addrs(TALLOC_CTX *mem_ctx, uint32_t *a_num,
struct rk_resource_record *rr, char ***cur_addrs, uint32_t total,
uint16_t port) struct dns_request *reply, int port)
{ {
char addrstr[INET6_ADDRSTRLEN]; char addrstr[INET6_ADDRSTRLEN];
char *addr; struct dns_rrec *rr;
char **addrs;
uint32_t i;
const char *addr;
switch (rr->type) { /* at most we over-allocate here, but not by much */
case rk_ns_t_a: addrs = talloc_realloc(mem_ctx, *cur_addrs, char *,
if (inet_ntop(AF_INET, rr->u.a, total + reply->num_answers);
addrstr, sizeof(addrstr)) == NULL) { if (!addrs) {
return NULL; return 0;
}
*cur_addrs = addrs;
for (i = 0; reply->answers[i]; i++) {
rr = reply->answers[i];
/* we are only interested in the IN class */
if (rr->r_class != DNS_CLASS_IN) {
continue;
}
if (rr->type == QTYPE_NS) {
/*
* After the record for NS will come the A or AAAA
* record of the NS.
*/
break;
}
/* verify we actually have a record here */
if (!rr->data) {
continue;
}
/* we are only interested in A and AAAA records */
switch (rr->type) {
case QTYPE_A:
addr = inet_ntop(AF_INET,
(struct in_addr *)rr->data,
addrstr, sizeof(addrstr));
if (addr == NULL) {
continue;
} }
break; break;
case QTYPE_AAAA:
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
case rk_ns_t_aaaa: addr = inet_ntop(AF_INET6,
if (inet_ntop(AF_INET6, (struct in6_addr *)rr->u.data, (struct in6_addr *)rr->data,
addrstr, sizeof(addrstr)) == NULL) { addrstr, sizeof(addrstr));
return NULL; #else
} addr = NULL;
break;
#endif #endif
if (addr == NULL) {
continue;
}
default: default:
return NULL; continue;
}
addrs[total] = talloc_asprintf(addrs, "%s@%u/%s",
addrstr, port,
rr->name->pLabelList->label);
if (addrs[total]) {
total++;
if (rr->type == QTYPE_A) {
(*a_num)++;
}
}
} }
addr = talloc_asprintf(mem_ctx, "%s@%u/%s", addrstr, return total;
port, rr->domain); }
return addr; static DNS_ERROR dns_lookup(TALLOC_CTX *mem_ctx, const char* name,
uint16_t q_type, struct dns_request **reply)
{
int len, rlen;
uint8_t *answer;
bool loop;
struct dns_buffer buf;
DNS_ERROR err;
/* give space for a good sized answer by default */
answer = NULL;
len = 1500;
do {
answer = talloc_realloc(mem_ctx, answer, uint8_t, len);
if (!answer) {
return ERROR_DNS_NO_MEMORY;
}
rlen = res_search(name, DNS_CLASS_IN, q_type, answer, len);
if (rlen == -1) {
if (len >= 65535) {
return ERROR_DNS_SOCKET_ERROR;
}
/* retry once with max packet size */
len = 65535;
loop = true;
} else if (rlen > len) {
len = rlen;
loop = true;
} else {
loop = false;
}
} while(loop);
buf.data = answer;
buf.size = rlen;
buf.offset = 0;
buf.error = ERROR_DNS_SUCCESS;
err = dns_unmarshall_request(mem_ctx, &buf, reply);
TALLOC_FREE(answer);
return err;
} }
static struct dns_records_container get_a_aaaa_records(TALLOC_CTX *mem_ctx, static struct dns_records_container get_a_aaaa_records(TALLOC_CTX *mem_ctx,
const char* name, const char* name,
int port) int port)
{ {
struct rk_dns_reply *reply, *reply2, *rep, *tmp[3]; struct dns_request *reply;
struct rk_resource_record *rr;
struct dns_records_container ret; struct dns_records_container ret;
char **addrs = NULL; char **addrs = NULL;
uint32_t count, count2, total; uint32_t a_num, total;
uint32_t i; uint16_t qtype;
TALLOC_CTX *tmp_ctx;
DNS_ERROR err;
memset(&ret, 0, sizeof(struct dns_records_container)); memset(&ret, 0, sizeof(struct dns_records_container));
tmp_ctx = talloc_new(mem_ctx);
if (!tmp_ctx) {
return ret;
}
qtype = QTYPE_AAAA;
/* this is the blocking call we are going to lots of trouble /* this is the blocking call we are going to lots of trouble
to avoid them in the parent */ to avoid them in the parent */
reply = rk_dns_lookup(name, "AAAA"); err = dns_lookup(tmp_ctx, name, qtype, &reply);
if (!ERR_DNS_IS_OK(err)) {
count = count2 = 0; qtype = QTYPE_A;
err = dns_lookup(tmp_ctx, name, qtype, &reply);
if (reply) { if (!ERR_DNS_IS_OK(err)) {
goto done;
count = count_dns_rr(reply->head, rk_ns_t_aaaa);
count2 = count_dns_rr(reply->head, rk_ns_t_a);
if (!count2) {
/*
* DNS server didn't returned A when asked for AAAA records.
* Most of the server do it, let's ask for A specificaly.
*/
reply2 = rk_dns_lookup(name, "A");
if (!reply2) {
return ret;
}
/* Some servers (Microsoft at least return here AAAA records .... */
count += count_dns_rr(reply2->head, rk_ns_t_aaaa);
count2 = count_dns_rr(reply2->head, rk_ns_t_a);
} else {
reply2 = NULL;
}
} else {
reply = rk_dns_lookup(name, "A");
if (!reply) {
return ret;
}
reply2 = NULL;
count = count_dns_rr(reply->head, rk_ns_t_a);
}
count += count2;
if (count == 0) {
goto done;
}
addrs = talloc_zero_array(mem_ctx, char*, count);
total = 0;
tmp[0] = reply;
tmp[1] = reply2;
tmp[2] = NULL;
/* Loop over all returned records and pick the records */
for (i=0; tmp[i] != NULL; i++) {
rep = tmp[i];
for (rr=rep->head; rr; rr=rr->next) {
/* we are only interested in the IN class */
if (rr->class != rk_ns_c_in) {
continue;
}
if (rr->type == rk_ns_t_ns) {
/*
* After the record for NS will come the A or AAAA
* record of the NS.
*/
break;
}
/* we are only interested in A and AAAA records */
if (rr->type != rk_ns_t_a && rr->type != rk_ns_t_aaaa) {
continue;
}
/* verify we actually have a record here */
if (!rr->u.data) {
continue;
}
addrs[total] = rr_to_string(addrs, rr, port);
if (addrs[total]) {
total++;
}
} }
} }
a_num = total = 0;
total = reply_to_addrs(tmp_ctx, &a_num, &addrs, total, reply, port);
if (qtype == QTYPE_AAAA && a_num == 0) {
/*
* DNS server didn't returned A when asked for AAAA records.
* Most of the server do it, let's ask for A specificaly.
*/
err = dns_lookup(tmp_ctx, name, QTYPE_A, &reply);
if (!ERR_DNS_IS_OK(err)) {
goto done;
}
total = reply_to_addrs(tmp_ctx, &a_num, &addrs, total,
reply, port);
}
if (total) { if (total) {
talloc_steal(mem_ctx, addrs);
ret.count = total; ret.count = total;
ret.list = addrs; ret.list = addrs;
} }
done: done:
if (reply != NULL) TALLOC_FREE(tmp_ctx);
rk_dns_free_data(reply);
if (reply2 != NULL)
rk_dns_free_data(reply2);
return ret; return ret;
} }
static struct dns_records_container get_srv_records(TALLOC_CTX *mem_ctx, static struct dns_records_container get_srv_records(TALLOC_CTX *mem_ctx,
const char* name) const char* name)
{ {
struct rk_dns_reply *reply;
struct rk_resource_record *rr;
struct dns_records_container ret; struct dns_records_container ret;
char **addrs = NULL; char **addrs = NULL;
uint32_t count, total; struct dns_rr_srv *dclist;
NTSTATUS status;
uint32_t total;
unsigned i;
int count;
memset(&ret, 0, sizeof(struct dns_records_container)); memset(&ret, 0, sizeof(struct dns_records_container));
/* this is the blocking call we are going to lots of trouble /* this is the blocking call we are going to lots of trouble
to avoid them in the parent */ to avoid them in the parent */
reply = rk_dns_lookup(name, "SRV"); status = ads_dns_lookup_srv(mem_ctx, NULL, name, &dclist, &count);
if (!NT_STATUS_IS_OK(status)) {
if (!reply) { return ret;
}
total = 0;
if (count == 0) {
return ret; return ret;
} }
rk_dns_srv_order(reply);
count = count_dns_rr(reply->head, rk_ns_t_srv);
total = 0;
if (count == 0) {
goto done;
}
/* Loop over all returned records and pick the records */ /* Loop over all returned records and pick the records */
for (rr=reply->head; rr; rr=rr->next) { for (i = 0; i < count; i++) {
struct dns_records_container c; struct dns_records_container c;
char* tmp_str; const char* tmp_str;
/* we are only interested in the IN class */
if (rr->class != rk_ns_c_in) {
continue;
}
/* we are only interested in SRV records */ tmp_str = dclist[i].hostname;
if (rr->type != rk_ns_t_srv) {
continue;
}
/* verify we actually have a srv record here */
if (!rr->u.srv) {
continue;
}
/* Verify we got a port */
if (rr->u.srv->port == 0) {
continue;
}
tmp_str = rr->u.srv->target;
if (strchr(tmp_str, '.') && tmp_str[strlen(tmp_str)-1] != '.') { if (strchr(tmp_str, '.') && tmp_str[strlen(tmp_str)-1] != '.') {
/* we are asking for a fully qualified name, but the /* we are asking for a fully qualified name, but the
name doesn't end in a '.'. We need to prevent the name doesn't end in a '.'. We need to prevent the
@ -340,7 +300,7 @@ static struct dns_records_container get_srv_records(TALLOC_CTX *mem_ctx,
tmp_str = talloc_asprintf(mem_ctx, "%s.", tmp_str); tmp_str = talloc_asprintf(mem_ctx, "%s.", tmp_str);
} }
c = get_a_aaaa_records(mem_ctx, tmp_str, rr->u.srv->port); c = get_a_aaaa_records(mem_ctx, tmp_str, dclist[i].port);
total += c.count; total += c.count;
if (addrs == NULL) { if (addrs == NULL) {
addrs = c.list; addrs = c.list;
@ -359,11 +319,6 @@ static struct dns_records_container get_srv_records(TALLOC_CTX *mem_ctx,
ret.list = addrs; ret.list = addrs;
} }
done:
if (reply != NULL)
rk_dns_free_data(reply);
return ret; return ret;
} }
/* /*

2
source4/libcli/wscript_build Normal file → Executable file
View File

@ -62,7 +62,7 @@ bld.SAMBA_SUBSYSTEM('LIBCLI_RESOLVE',
bld.SAMBA_SUBSYSTEM('LP_RESOLVE', bld.SAMBA_SUBSYSTEM('LP_RESOLVE',
source='resolve/bcast.c resolve/nbtlist.c resolve/wins.c resolve/dns_ex.c resolve/file.c resolve/host.c resolve/resolve_lp.c', source='resolve/bcast.c resolve/nbtlist.c resolve/wins.c resolve/dns_ex.c resolve/file.c resolve/host.c resolve/resolve_lp.c',
autoproto='resolve/lp_proto.h', autoproto='resolve/lp_proto.h',
deps='cli-nbt samba-hostconfig netif' deps='cli-nbt samba-hostconfig netif addns'
) )