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>
32 LDAP_CONST char *dn_in,
40 struct berval domain = { 0, NULL };
41 static const struct berval DC = BER_BVC("DC");
42 static const struct berval DCOID = BER_BVC("0.9.2342.19200300.100.1.25");
44 assert( dn_in != NULL );
45 assert( domainp != NULL );
49 if ( ldap_str2dn( dn_in, &dn, LDAP_DN_FORMAT_LDAP ) != LDAP_SUCCESS ) {
53 if( dn ) for( i=0; dn[i] != NULL; i++ ) {
56 for( j=0; rdn[j] != NULL; j++ ) {
59 if( rdn[j+1] == NULL &&
60 (ava->la_flags & LDAP_AVA_STRING) &&
61 ava->la_value.bv_len &&
62 ( ber_bvstrcasecmp( &ava->la_attr, &DC ) == 0
63 || ber_bvstrcasecmp( &ava->la_attr, &DCOID ) == 0 ) )
65 if( domain.bv_len == 0 ) {
66 ndomain = LDAP_REALLOC( domain.bv_val,
67 ava->la_value.bv_len + 1);
69 if( ndomain == NULL ) {
73 domain.bv_val = ndomain;
75 AC_MEMCPY( domain.bv_val, ava->la_value.bv_val,
76 ava->la_value.bv_len );
78 domain.bv_len = ava->la_value.bv_len;
79 domain.bv_val[domain.bv_len] = '\0';
82 ndomain = LDAP_REALLOC( domain.bv_val,
83 ava->la_value.bv_len + sizeof(".") + domain.bv_len );
85 if( ndomain == NULL ) {
89 domain.bv_val = ndomain;
90 domain.bv_val[domain.bv_len++] = '.';
91 AC_MEMCPY( &domain.bv_val[domain.bv_len],
92 ava->la_value.bv_val, ava->la_value.bv_len );
93 domain.bv_len += ava->la_value.bv_len;
94 domain.bv_val[domain.bv_len] = '\0';
103 if( domain.bv_len == 0 && domain.bv_val != NULL ) {
104 LDAP_FREE( domain.bv_val );
105 domain.bv_val = NULL;
109 *domainp = domain.bv_val;
114 LDAP_FREE( domain.bv_val );
119 LDAP_CONST char *domain_in,
122 char *domain, *s, *tok_r, *dn, *dntmp;
125 assert( domain_in != NULL );
126 assert( dnp != NULL );
128 domain = LDAP_STRDUP(domain_in);
129 if (domain == NULL) {
130 return LDAP_NO_MEMORY;
135 for (s = ldap_pvt_strtok(domain, ".", &tok_r);
137 s = ldap_pvt_strtok(NULL, ".", &tok_r))
139 size_t len = strlen(s);
141 dntmp = (char *) LDAP_REALLOC(dn, loc + sizeof(",dc=") + len );
146 return LDAP_NO_MEMORY;
152 /* not first time. */
153 strcpy(dn + loc, ",");
156 strcpy(dn + loc, "dc=");
157 loc += sizeof("dc=")-1;
169 * Lookup and return LDAP servers for domain (using the DNS
170 * SRV record _ldap._tcp.domain).
172 int ldap_domain2hostlist(
173 LDAP_CONST char *domain,
176 #ifdef HAVE_RES_QUERY
177 #define DNSBUFSIZ (64*1024)
179 char *hostlist = NULL;
180 int rc, len, cur = 0;
181 unsigned char reply[DNSBUFSIZ];
183 assert( domain != NULL );
184 assert( list != NULL );
186 if( *domain == '\0' ) {
187 return LDAP_PARAM_ERROR;
190 request = LDAP_MALLOC(strlen(domain) + sizeof("_ldap._tcp."));
191 if (request == NULL) {
192 return LDAP_NO_MEMORY;
194 sprintf(request, "_ldap._tcp.%s", domain);
196 #ifdef LDAP_R_COMPILE
197 ldap_pvt_thread_mutex_lock(&ldap_int_resolv_mutex);
200 rc = LDAP_UNAVAILABLE;
202 /* Bind 8/9 interface */
203 len = res_query(request, ns_c_in, ns_t_srv, reply, sizeof(reply));
205 /* Bind 4 interface */
209 len = res_query(request, C_IN, T_SRV, reply, sizeof(reply));
213 char host[DNSBUFSIZ];
216 /* int priority, weight; */
218 /* Parse out query */
221 /* Bind 8/9 interface */
224 /* Bind 4 interface */
227 status = dn_expand(reply, reply + len, p, host, sizeof(host));
234 while (p < reply + len) {
235 int type, class, ttl, size;
236 status = dn_expand(reply, reply + len, p, host, sizeof(host));
241 type = (p[0] << 8) | p[1];
243 class = (p[0] << 8) | p[1];
245 ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
247 size = (p[0] << 8) | p[1];
251 status = dn_expand(reply, reply + len, p + 6, host, sizeof(host));
255 /* ignore priority and weight for now */
256 /* priority = (p[0] << 8) | p[1]; */
257 /* weight = (p[2] << 8) | p[3]; */
258 port = (p[4] << 8) | p[5];
260 buflen = strlen(host) + sizeof(":65355 ");
261 hostlist = (char *) LDAP_REALLOC(hostlist, cur + buflen);
262 if (hostlist == NULL) {
267 /* not first time around */
268 hostlist[cur++] = ' ';
270 cur += sprintf(&hostlist[cur], "%s:%hd", host, port);
275 if (hostlist == NULL) {
276 /* No LDAP servers found in DNS. */
277 rc = LDAP_UNAVAILABLE;
285 #ifdef LDAP_R_COMPILE
286 ldap_pvt_thread_mutex_unlock(&ldap_int_resolv_mutex);
289 if (request != NULL) {
292 if (rc != LDAP_SUCCESS && hostlist != NULL) {
297 return LDAP_NOT_SUPPORTED;
298 #endif /* HAVE_RES_QUERY */