3 * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
8 * locate LDAP servers using DNS SRV records.
9 * Location code based on MIT Kerberos KDC location code.
15 #include <ac/stdlib.h>
18 #include <ac/socket.h>
19 #include <ac/string.h>
24 #ifdef HAVE_ARPA_NAMESER_H
25 #include <arpa/nameser.h>
31 /* Sometimes this is not defined. */
37 LDAP_CONST char *dn_in,
45 struct berval domain = { 0, NULL };
46 static const struct berval DC = BER_BVC("DC");
47 static const struct berval DCOID = BER_BVC("0.9.2342.19200300.100.1.25");
49 assert( dn_in != NULL );
50 assert( domainp != NULL );
54 if ( ldap_str2dn( dn_in, &dn, LDAP_DN_FORMAT_LDAP ) != LDAP_SUCCESS ) {
58 if( dn ) for( i=0; dn[i] != NULL; i++ ) {
61 for( j=0; rdn[j] != NULL; j++ ) {
64 if( rdn[j+1] == NULL &&
65 (ava->la_flags & LDAP_AVA_STRING) &&
66 ava->la_value.bv_len &&
67 ( ber_bvstrcasecmp( &ava->la_attr, &DC ) == 0
68 || ber_bvstrcasecmp( &ava->la_attr, &DCOID ) == 0 ) )
70 if( domain.bv_len == 0 ) {
71 ndomain = LDAP_REALLOC( domain.bv_val,
72 ava->la_value.bv_len + 1);
74 if( ndomain == NULL ) {
78 domain.bv_val = ndomain;
80 AC_MEMCPY( domain.bv_val, ava->la_value.bv_val,
81 ava->la_value.bv_len );
83 domain.bv_len = ava->la_value.bv_len;
84 domain.bv_val[domain.bv_len] = '\0';
87 ndomain = LDAP_REALLOC( domain.bv_val,
88 ava->la_value.bv_len + sizeof(".") + domain.bv_len );
90 if( ndomain == NULL ) {
94 domain.bv_val = ndomain;
95 domain.bv_val[domain.bv_len++] = '.';
96 AC_MEMCPY( &domain.bv_val[domain.bv_len],
97 ava->la_value.bv_val, ava->la_value.bv_len );
98 domain.bv_len += ava->la_value.bv_len;
99 domain.bv_val[domain.bv_len] = '\0';
108 if( domain.bv_len == 0 && domain.bv_val != NULL ) {
109 LDAP_FREE( domain.bv_val );
110 domain.bv_val = NULL;
114 *domainp = domain.bv_val;
119 LDAP_FREE( domain.bv_val );
124 LDAP_CONST char *domain_in,
127 char *domain, *s, *tok_r, *dn, *dntmp;
130 assert( domain_in != NULL );
131 assert( dnp != NULL );
133 domain = LDAP_STRDUP(domain_in);
134 if (domain == NULL) {
135 return LDAP_NO_MEMORY;
140 for (s = ldap_pvt_strtok(domain, ".", &tok_r);
142 s = ldap_pvt_strtok(NULL, ".", &tok_r))
144 size_t len = strlen(s);
146 dntmp = (char *) LDAP_REALLOC(dn, loc + sizeof(",dc=") + len );
151 return LDAP_NO_MEMORY;
157 /* not first time. */
158 strcpy(dn + loc, ",");
161 strcpy(dn + loc, "dc=");
162 loc += sizeof("dc=")-1;
174 * Lookup and return LDAP servers for domain (using the DNS
175 * SRV record _ldap._tcp.domain).
177 int ldap_domain2hostlist(
178 LDAP_CONST char *domain,
181 #ifdef HAVE_RES_QUERY
182 #define DNSBUFSIZ (64*1024)
184 char *hostlist = NULL;
185 int rc, len, cur = 0;
186 unsigned char reply[DNSBUFSIZ];
188 assert( domain != NULL );
189 assert( list != NULL );
191 if( *domain == '\0' ) {
192 return LDAP_PARAM_ERROR;
195 request = LDAP_MALLOC(strlen(domain) + sizeof("_ldap._tcp."));
196 if (request == NULL) {
197 return LDAP_NO_MEMORY;
199 sprintf(request, "_ldap._tcp.%s", domain);
201 #ifdef LDAP_R_COMPILE
202 ldap_pvt_thread_mutex_lock(&ldap_int_resolv_mutex);
205 rc = LDAP_UNAVAILABLE;
206 len = res_query(request, C_IN, T_SRV, reply, sizeof(reply));
209 char host[DNSBUFSIZ];
212 /* int priority, weight; */
214 /* Parse out query */
217 status = dn_expand(reply, reply + len, p, host, sizeof(host));
224 while (p < reply + len) {
225 int type, class, ttl, size;
226 status = dn_expand(reply, reply + len, p, host, sizeof(host));
231 type = (p[0] << 8) | p[1];
233 class = (p[0] << 8) | p[1];
235 ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
237 size = (p[0] << 8) | p[1];
241 status = dn_expand(reply, reply + len, p + 6, host, sizeof(host));
245 /* ignore priority and weight for now */
246 /* priority = (p[0] << 8) | p[1]; */
247 /* weight = (p[2] << 8) | p[3]; */
248 port = (p[4] << 8) | p[5];
250 buflen = strlen(host) + sizeof(":65355 ");
251 hostlist = (char *) LDAP_REALLOC(hostlist, cur + buflen);
252 if (hostlist == NULL) {
257 /* not first time around */
258 hostlist[cur++] = ' ';
260 cur += sprintf(&hostlist[cur], "%s:%hd", host, port);
265 if (hostlist == NULL) {
266 /* No LDAP servers found in DNS. */
267 rc = LDAP_UNAVAILABLE;
275 #ifdef LDAP_R_COMPILE
276 ldap_pvt_thread_mutex_unlock(&ldap_int_resolv_mutex);
279 if (request != NULL) {
282 if (rc != LDAP_SUCCESS && hostlist != NULL) {
287 return LDAP_NOT_SUPPORTED;
288 #endif /* HAVE_RES_QUERY */