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, *dntmp;
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))
141 size_t len = strlen(s);
143 dntmp = (char *) LDAP_REALLOC(dn, loc + sizeof(",dc=") + len );
147 return LDAP_NO_MEMORY;
153 /* not first time. */
154 strcpy(dn + loc, ",");
157 strcpy(dn + loc, "dc=");
158 loc += sizeof("dc=")-1;
170 * Lookup and return LDAP servers for domain (using the DNS
171 * SRV record _ldap._tcp.domain).
173 int ldap_domain2hostlist(
174 LDAP_CONST char *domain,
177 #ifdef HAVE_RES_QUERY
178 #define DNSBUFSIZ (64*1024)
180 char *hostlist = NULL;
181 int rc, len, cur = 0;
182 unsigned char reply[DNSBUFSIZ];
184 assert( domain != NULL );
185 assert( list != NULL );
187 if( *domain == '\0' ) {
188 return LDAP_PARAM_ERROR;
191 request = LDAP_MALLOC(strlen(domain) + sizeof("_ldap._tcp."));
192 if (request == NULL) {
193 return LDAP_NO_MEMORY;
195 sprintf(request, "_ldap._tcp.%s", domain);
197 #ifdef LDAP_R_COMPILE
198 ldap_pvt_thread_mutex_lock(&ldap_int_resolv_mutex);
201 rc = LDAP_UNAVAILABLE;
202 len = res_query(request, C_IN, T_SRV, reply, sizeof(reply));
205 char host[DNSBUFSIZ];
208 /* int priority, weight; */
210 /* Parse out query */
213 status = dn_expand(reply, reply + len, p, host, sizeof(host));
220 while (p < reply + len) {
221 int type, class, ttl, size;
222 status = dn_expand(reply, reply + len, p, host, sizeof(host));
227 type = (p[0] << 8) | p[1];
229 class = (p[0] << 8) | p[1];
231 ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
233 size = (p[0] << 8) | p[1];
237 status = dn_expand(reply, reply + len, p + 6, host, sizeof(host));
241 /* ignore priority and weight for now */
242 /* priority = (p[0] << 8) | p[1]; */
243 /* weight = (p[2] << 8) | p[3]; */
244 port = (p[4] << 8) | p[5];
246 buflen = strlen(host) + sizeof(":65355 ");
247 hostlist = (char *) LDAP_REALLOC(hostlist, cur + buflen);
248 if (hostlist == NULL) {
253 /* not first time around */
254 hostlist[cur++] = ' ';
256 cur += sprintf(&hostlist[cur], "%s:%hd", host, port);
261 if (hostlist == NULL) {
262 /* No LDAP servers found in DNS. */
263 rc = LDAP_UNAVAILABLE;
271 #ifdef LDAP_R_COMPILE
272 ldap_pvt_thread_mutex_unlock(&ldap_int_resolv_mutex);
275 if (request != NULL) {
278 if (rc != LDAP_SUCCESS && hostlist != NULL) {
283 return LDAP_NOT_SUPPORTED;
284 #endif /* HAVE_RES_QUERY */