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 );
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 );
148 return LDAP_NO_MEMORY;
154 /* not first time. */
155 strcpy(dn + loc, ",");
158 strcpy(dn + loc, "dc=");
159 loc += sizeof("dc=")-1;
171 * Lookup and return LDAP servers for domain (using the DNS
172 * SRV record _ldap._tcp.domain).
174 int ldap_domain2hostlist(
175 LDAP_CONST char *domain,
178 #ifdef HAVE_RES_QUERY
179 #define DNSBUFSIZ (64*1024)
181 char *hostlist = NULL;
182 int rc, len, cur = 0;
183 unsigned char reply[DNSBUFSIZ];
185 assert( domain != NULL );
186 assert( list != NULL );
188 if( *domain == '\0' ) {
189 return LDAP_PARAM_ERROR;
192 request = LDAP_MALLOC(strlen(domain) + sizeof("_ldap._tcp."));
193 if (request == NULL) {
194 return LDAP_NO_MEMORY;
196 sprintf(request, "_ldap._tcp.%s", domain);
198 #ifdef LDAP_R_COMPILE
199 ldap_pvt_thread_mutex_lock(&ldap_int_resolv_mutex);
202 rc = LDAP_UNAVAILABLE;
203 len = res_query(request, C_IN, T_SRV, reply, sizeof(reply));
206 char host[DNSBUFSIZ];
209 /* int priority, weight; */
211 /* Parse out query */
214 status = dn_expand(reply, reply + len, p, host, sizeof(host));
221 while (p < reply + len) {
222 int type, class, ttl, size;
223 status = dn_expand(reply, reply + len, p, host, sizeof(host));
228 type = (p[0] << 8) | p[1];
230 class = (p[0] << 8) | p[1];
232 ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
234 size = (p[0] << 8) | p[1];
238 status = dn_expand(reply, reply + len, p + 6, host, sizeof(host));
242 /* ignore priority and weight for now */
243 /* priority = (p[0] << 8) | p[1]; */
244 /* weight = (p[2] << 8) | p[3]; */
245 port = (p[4] << 8) | p[5];
247 buflen = strlen(host) + sizeof(":65355 ");
248 hostlist = (char *) LDAP_REALLOC(hostlist, cur + buflen);
249 if (hostlist == NULL) {
254 /* not first time around */
255 hostlist[cur++] = ' ';
257 cur += sprintf(&hostlist[cur], "%s:%hd", host, port);
262 if (hostlist == NULL) {
263 /* No LDAP servers found in DNS. */
264 rc = LDAP_UNAVAILABLE;
272 #ifdef LDAP_R_COMPILE
273 ldap_pvt_thread_mutex_unlock(&ldap_int_resolv_mutex);
276 if (request != NULL) {
279 if (rc != LDAP_SUCCESS && hostlist != NULL) {
284 return LDAP_NOT_SUPPORTED;
285 #endif /* HAVE_RES_QUERY */