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,
45 struct berval domain = { 0, NULL };
46 const static struct berval DC = BER_BVC("DC");
47 const static struct berval DCOID = BER_BVC("0.9.2342.19200300.100.1.25");
49 assert( dn_in != NULL );
50 assert( domainp != NULL );
52 if ( ldap_str2dn( dn_in, &dn, LDAP_DN_FORMAT_LDAP ) != LDAP_SUCCESS ) {
56 if( dn ) for( i=0; (*dn)[i] != NULL; i++ ) {
59 for( j=0; (*rdn)[j] != NULL; j++ ) {
62 if( (*dn)[i][j][1] == NULL &&
63 !ava->la_flags && ava->la_value.bv_len &&
64 ( ber_bvstrcasecmp( &ava->la_attr, &DC ) == 0
65 || ber_bvstrcasecmp( &ava->la_attr, &DCOID ) == 0 ) )
67 if( domain.bv_len == 0 ) {
68 ndomain = LDAP_REALLOC( domain.bv_val,
69 ava->la_value.bv_len + 1);
71 if( ndomain == NULL ) {
75 domain.bv_val = ndomain;
77 AC_MEMCPY( domain.bv_val, ava->la_value.bv_val,
78 ava->la_value.bv_len );
80 domain.bv_len = ava->la_value.bv_len;
81 domain.bv_val[domain.bv_len] = '\0';
84 ndomain = LDAP_REALLOC( domain.bv_val,
85 ava->la_value.bv_len + sizeof(".") + domain.bv_len );
87 if( ndomain == NULL ) {
91 domain.bv_val = ndomain;
92 domain.bv_val[domain.bv_len++] = '.';
93 AC_MEMCPY( &domain.bv_val[domain.bv_len],
94 ava->la_value.bv_val, ava->la_value.bv_len );
95 domain.bv_len += ava->la_value.bv_len;
96 domain.bv_val[domain.bv_len] = '\0';
105 if( domain.bv_len == 0 && domain.bv_val != NULL ) {
106 LDAP_FREE( domain.bv_val );
107 domain.bv_val = NULL;
111 *domainp = domain.bv_val;
116 LDAP_FREE( domain.bv_val );
121 LDAP_CONST char *domain_in,
124 char *domain, *s, *tok_r, *dn;
127 assert( domain_in != NULL );
128 assert( dnp != NULL );
130 domain = LDAP_STRDUP(domain_in);
131 if (domain == NULL) {
132 return LDAP_NO_MEMORY;
137 for (s = ldap_pvt_strtok(domain, ".", &tok_r);
139 s = ldap_pvt_strtok(NULL, ".", &tok_r)) {
140 size_t len = strlen(s);
142 dn = (char *) LDAP_REALLOC(dn, loc + sizeof(",dc=") + len );
145 return LDAP_NO_MEMORY;
148 /* not first time. */
149 strcpy(dn + loc, ",");
152 strcpy(dn + loc, "dc=");
153 loc += sizeof("dc=")-1;
167 * Lookup and return LDAP servers for domain (using the DNS
168 * SRV record _ldap._tcp.domain).
170 int ldap_domain2hostlist(
171 LDAP_CONST char *domain,
174 #ifdef HAVE_RES_QUERY
176 char *hostlist = NULL;
177 int rc, len, cur = 0;
178 unsigned char reply[1024];
180 assert( domain != NULL );
181 assert( list != NULL );
183 if( *domain == '\0' ) {
184 return LDAP_PARAM_ERROR;
187 request = LDAP_MALLOC(strlen(domain) + sizeof("_ldap._tcp."));
188 if (request == NULL) {
189 return LDAP_NO_MEMORY;
191 sprintf(request, "_ldap._tcp.%s", domain);
193 #ifdef LDAP_R_COMPILE
194 ldap_pvt_thread_mutex_lock(&ldap_int_resolv_mutex);
197 rc = LDAP_UNAVAILABLE;
198 len = res_query(request, C_IN, T_SRV, reply, sizeof(reply));
204 /* int priority, weight; */
206 /* Parse out query */
209 status = dn_expand(reply, reply + len, p, host, sizeof(host));
216 while (p < reply + len) {
217 int type, class, ttl, size;
218 status = dn_expand(reply, reply + len, p, host, sizeof(host));
223 type = (p[0] << 8) | p[1];
225 class = (p[0] << 8) | p[1];
227 ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
229 size = (p[0] << 8) | p[1];
233 status = dn_expand(reply, reply + len, p + 6, host, sizeof(host));
237 /* ignore priority and weight for now */
238 /* priority = (p[0] << 8) | p[1]; */
239 /* weight = (p[2] << 8) | p[3]; */
240 port = (p[4] << 8) | p[5];
242 buflen = strlen(host) + sizeof(":65355 ");
243 hostlist = (char *) LDAP_REALLOC(hostlist, cur + buflen);
244 if (hostlist == NULL) {
249 /* not first time around */
250 hostlist[cur++] = ' ';
252 cur += sprintf(&hostlist[cur], "%s:%hd", host, port);
257 if (hostlist == NULL) {
258 /* No LDAP servers found in DNS. */
259 rc = LDAP_UNAVAILABLE;
267 #ifdef LDAP_R_COMPILE
268 ldap_pvt_thread_mutex_unlock(&ldap_int_resolv_mutex);
271 if (request != NULL) {
274 if (rc != LDAP_SUCCESS && hostlist != NULL) {
279 return LDAP_NOT_SUPPORTED;
280 #endif /* HAVE_RES_QUERY */