1
/* $OpenLDAP: pkg/ldap/libraries/libldap/dnssrv.c,v 1.39.2.4 2008/02/11 23:26:41 kurt Exp $ */
2
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4
* Copyright 1998-2008 The OpenLDAP Foundation.
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted only as authorized by the OpenLDAP
11
* A copy of this license is available in the file LICENSE in the
12
* top-level directory of the distribution or, alternatively, at
13
* <http://www.OpenLDAP.org/license.html>.
17
* locate LDAP servers using DNS SRV records.
18
* Location code based on MIT Kerberos KDC location code.
24
#include <ac/stdlib.h>
27
#include <ac/socket.h>
28
#include <ac/string.h>
33
#ifdef HAVE_ARPA_NAMESER_H
34
#include <arpa/nameser.h>
41
LDAP_CONST char *dn_in,
49
struct berval domain = BER_BVNULL;
50
static const struct berval DC = BER_BVC("DC");
51
static const struct berval DCOID = BER_BVC("0.9.2342.19200300.100.1.25");
53
assert( dn_in != NULL );
54
assert( domainp != NULL );
58
if ( ldap_str2dn( dn_in, &dn, LDAP_DN_FORMAT_LDAP ) != LDAP_SUCCESS ) {
62
if( dn ) for( i=0; dn[i] != NULL; i++ ) {
65
for( j=0; rdn[j] != NULL; j++ ) {
68
if( rdn[j+1] == NULL &&
69
(ava->la_flags & LDAP_AVA_STRING) &&
70
ava->la_value.bv_len &&
71
( ber_bvstrcasecmp( &ava->la_attr, &DC ) == 0
72
|| ber_bvcmp( &ava->la_attr, &DCOID ) == 0 ) )
74
if( domain.bv_len == 0 ) {
75
ndomain = LDAP_REALLOC( domain.bv_val,
76
ava->la_value.bv_len + 1);
78
if( ndomain == NULL ) {
82
domain.bv_val = ndomain;
84
AC_MEMCPY( domain.bv_val, ava->la_value.bv_val,
85
ava->la_value.bv_len );
87
domain.bv_len = ava->la_value.bv_len;
88
domain.bv_val[domain.bv_len] = '\0';
91
ndomain = LDAP_REALLOC( domain.bv_val,
92
ava->la_value.bv_len + sizeof(".") + domain.bv_len );
94
if( ndomain == NULL ) {
98
domain.bv_val = ndomain;
99
domain.bv_val[domain.bv_len++] = '.';
100
AC_MEMCPY( &domain.bv_val[domain.bv_len],
101
ava->la_value.bv_val, ava->la_value.bv_len );
102
domain.bv_len += ava->la_value.bv_len;
103
domain.bv_val[domain.bv_len] = '\0';
112
if( domain.bv_len == 0 && domain.bv_val != NULL ) {
113
LDAP_FREE( domain.bv_val );
114
domain.bv_val = NULL;
118
*domainp = domain.bv_val;
123
LDAP_FREE( domain.bv_val );
128
LDAP_CONST char *domain_in,
131
char *domain, *s, *tok_r, *dn, *dntmp;
134
assert( domain_in != NULL );
135
assert( dnp != NULL );
137
domain = LDAP_STRDUP(domain_in);
138
if (domain == NULL) {
139
return LDAP_NO_MEMORY;
144
for (s = ldap_pvt_strtok(domain, ".", &tok_r);
146
s = ldap_pvt_strtok(NULL, ".", &tok_r))
148
size_t len = strlen(s);
150
dntmp = (char *) LDAP_REALLOC(dn, loc + sizeof(",dc=") + len );
155
return LDAP_NO_MEMORY;
161
/* not first time. */
162
strcpy(dn + loc, ",");
165
strcpy(dn + loc, "dc=");
166
loc += sizeof("dc=")-1;
178
* Lookup and return LDAP servers for domain (using the DNS
179
* SRV record _ldap._tcp.domain).
181
int ldap_domain2hostlist(
182
LDAP_CONST char *domain,
185
#ifdef HAVE_RES_QUERY
186
#define DNSBUFSIZ (64*1024)
188
char *hostlist = NULL;
189
int rc, len, cur = 0;
190
unsigned char reply[DNSBUFSIZ];
192
assert( domain != NULL );
193
assert( list != NULL );
195
if( *domain == '\0' ) {
196
return LDAP_PARAM_ERROR;
199
request = LDAP_MALLOC(strlen(domain) + sizeof("_ldap._tcp."));
200
if (request == NULL) {
201
return LDAP_NO_MEMORY;
203
sprintf(request, "_ldap._tcp.%s", domain);
205
#ifdef LDAP_R_COMPILE
206
ldap_pvt_thread_mutex_lock(&ldap_int_resolv_mutex);
209
rc = LDAP_UNAVAILABLE;
211
/* Bind 8/9 interface */
212
len = res_query(request, ns_c_in, ns_t_srv, reply, sizeof(reply));
214
# define T_SRV ns_t_srv
217
/* Bind 4 interface */
222
len = res_query(request, C_IN, T_SRV, reply, sizeof(reply));
226
char host[DNSBUFSIZ];
229
/* int priority, weight; */
231
/* Parse out query */
235
/* Bind 8/9 interface */
237
#elif defined(HFIXEDSZ)
238
/* Bind 4 interface w/ HFIXEDSZ */
241
/* Bind 4 interface w/o HFIXEDSZ */
245
status = dn_expand(reply, reply + len, p, host, sizeof(host));
252
while (p < reply + len) {
253
int type, class, ttl, size;
254
status = dn_expand(reply, reply + len, p, host, sizeof(host));
259
type = (p[0] << 8) | p[1];
261
class = (p[0] << 8) | p[1];
263
ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
265
size = (p[0] << 8) | p[1];
269
status = dn_expand(reply, reply + len, p + 6, host, sizeof(host));
273
/* ignore priority and weight for now */
274
/* priority = (p[0] << 8) | p[1]; */
275
/* weight = (p[2] << 8) | p[3]; */
276
port = (p[4] << 8) | p[5];
278
if ( port == 0 || host[ 0 ] == '\0' ) {
282
buflen = strlen(host) + STRLENOF(":65355 ");
283
hostlist = (char *) LDAP_REALLOC(hostlist, cur + buflen + 1);
284
if (hostlist == NULL) {
289
/* not first time around */
290
hostlist[cur++] = ' ';
292
cur += sprintf(&hostlist[cur], "%s:%hd", host, port);
298
if (hostlist == NULL) {
299
/* No LDAP servers found in DNS. */
300
rc = LDAP_UNAVAILABLE;
308
#ifdef LDAP_R_COMPILE
309
ldap_pvt_thread_mutex_unlock(&ldap_int_resolv_mutex);
312
if (request != NULL) {
315
if (rc != LDAP_SUCCESS && hostlist != NULL) {
320
return LDAP_NOT_SUPPORTED;
321
#endif /* HAVE_RES_QUERY */