3 * Copyright 1998-2002 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,
44 if( dn_in == NULL || domainp == NULL ) {
48 dn = ldap_explode_dn( dn_in, 0 );
54 for( i=0; dn[i] != NULL; i++ ) {
55 char ** rdn = ldap_explode_rdn( dn[i], 0 );
57 if( rdn == NULL || *rdn == NULL ) {
65 if( rdn[1] == NULL ) {
72 #define LDAP_DCOID "0.9.2342.19200300.100.1.25="
74 if( strncasecmp( rdn[0],
75 LDAP_DC, sizeof(LDAP_DC)-1 ) == 0 )
77 dc = &rdn[0][sizeof(LDAP_DC)-1];
79 } else if( strncmp( rdn[0],
80 LDAP_DCOID, sizeof(LDAP_DCOID)-1 ) == 0 )
82 dc = &rdn[0][sizeof(LDAP_DCOID)-1];
92 /* dc value is empty! */
100 ndomain = LDAP_REALLOC( domain,
101 ( domain == NULL ? 0 : strlen(domain) )
102 + strlen(dc) + sizeof(".") );
104 if( ndomain == NULL ) {
112 if( domain == NULL ) {
115 strcat( ndomain, "." );
118 strcat( ndomain, dc );
126 * multi-valued RDN or fall thru
134 if( domain != NULL && *domain == '\0' ) {
144 LDAP_CONST char *domain_in,
147 char *domain, *s, *tok_r, *dn;
150 if (domain_in == NULL || dnp == NULL) {
151 return LDAP_NO_MEMORY;
153 domain = LDAP_STRDUP(domain_in);
154 if (domain == NULL) {
155 return LDAP_NO_MEMORY;
160 for (s = ldap_pvt_strtok(domain, ".", &tok_r);
162 s = ldap_pvt_strtok(NULL, ".", &tok_r)) {
163 size_t len = strlen(s);
165 dn = (char *) LDAP_REALLOC(dn, loc + sizeof(",dc=") + len );
168 return LDAP_NO_MEMORY;
171 /* not first time. */
172 strcpy(dn + loc, ",");
175 strcpy(dn + loc, "dc=");
176 loc += sizeof("dc=")-1;
190 * Lookup and return LDAP servers for domain (using the DNS
191 * SRV record _ldap._tcp.domain).
193 int ldap_domain2hostlist(
194 LDAP_CONST char *domain,
197 #ifdef HAVE_RES_QUERY
199 char *hostlist = NULL;
200 int rc, len, cur = 0;
201 unsigned char reply[1024];
203 if( domain == NULL || *domain == '\0' ) {
204 return LDAP_PARAM_ERROR;
208 return LDAP_PARAM_ERROR;
211 request = LDAP_MALLOC(strlen(domain) + sizeof("_ldap._tcp."));
212 if (request == NULL) {
213 return LDAP_NO_MEMORY;
215 sprintf(request, "_ldap._tcp.%s", domain);
217 #ifdef LDAP_R_COMPILE
218 ldap_pvt_thread_mutex_lock(&ldap_int_resolv_mutex);
221 rc = LDAP_UNAVAILABLE;
222 len = res_query(request, C_IN, T_SRV, reply, sizeof(reply));
228 /* int priority, weight; */
230 /* Parse out query */
233 status = dn_expand(reply, reply + len, p, host, sizeof(host));
240 while (p < reply + len) {
241 int type, class, ttl, size;
242 status = dn_expand(reply, reply + len, p, host, sizeof(host));
247 type = (p[0] << 8) | p[1];
249 class = (p[0] << 8) | p[1];
251 ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
253 size = (p[0] << 8) | p[1];
257 status = dn_expand(reply, reply + len, p + 6, host, sizeof(host));
261 /* ignore priority and weight for now */
262 /* priority = (p[0] << 8) | p[1]; */
263 /* weight = (p[2] << 8) | p[3]; */
264 port = (p[4] << 8) | p[5];
266 buflen = strlen(host) + sizeof(":65355");
267 hostlist = (char *) LDAP_REALLOC(hostlist, cur + buflen);
268 if (hostlist == NULL) {
273 /* not first time around */
274 hostlist[cur++] = ' ';
276 cur += sprintf(&hostlist[cur], "%s:%hd", host, port);
281 if (hostlist == NULL) {
282 /* No LDAP servers found in DNS. */
283 rc = LDAP_UNAVAILABLE;
291 #ifdef LDAP_R_COMPILE
292 ldap_pvt_thread_mutex_unlock(&ldap_int_resolv_mutex);
295 if (request != NULL) {
298 if (rc != LDAP_SUCCESS && hostlist != NULL) {
303 return LDAP_NOT_SUPPORTED;
304 #endif /* HAVE_RES_QUERY */