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
175 #define DNSBUFSIZ (64*1024)
177 char *hostlist = NULL;
178 int rc, len, cur = 0;
179 unsigned char reply[DNSBUFSIZ];
181 assert( domain != NULL );
182 assert( list != NULL );
184 if( *domain == '\0' ) {
185 return LDAP_PARAM_ERROR;
188 request = LDAP_MALLOC(strlen(domain) + sizeof("_ldap._tcp."));
189 if (request == NULL) {
190 return LDAP_NO_MEMORY;
192 sprintf(request, "_ldap._tcp.%s", domain);
194 #ifdef LDAP_R_COMPILE
195 ldap_pvt_thread_mutex_lock(&ldap_int_resolv_mutex);
198 rc = LDAP_UNAVAILABLE;
199 len = res_query(request, C_IN, T_SRV, reply, sizeof(reply));
202 char host[DNSBUFSIZ];
205 /* int priority, weight; */
207 /* Parse out query */
210 status = dn_expand(reply, reply + len, p, host, sizeof(host));
217 while (p < reply + len) {
218 int type, class, ttl, size;
219 status = dn_expand(reply, reply + len, p, host, sizeof(host));
224 type = (p[0] << 8) | p[1];
226 class = (p[0] << 8) | p[1];
228 ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
230 size = (p[0] << 8) | p[1];
234 status = dn_expand(reply, reply + len, p + 6, host, sizeof(host));
238 /* ignore priority and weight for now */
239 /* priority = (p[0] << 8) | p[1]; */
240 /* weight = (p[2] << 8) | p[3]; */
241 port = (p[4] << 8) | p[5];
243 buflen = strlen(host) + sizeof(":65355 ");
244 hostlist = (char *) LDAP_REALLOC(hostlist, cur + buflen);
245 if (hostlist == NULL) {
250 /* not first time around */
251 hostlist[cur++] = ' ';
253 cur += sprintf(&hostlist[cur], "%s:%hd", host, port);
258 if (hostlist == NULL) {
259 /* No LDAP servers found in DNS. */
260 rc = LDAP_UNAVAILABLE;
268 #ifdef LDAP_R_COMPILE
269 ldap_pvt_thread_mutex_unlock(&ldap_int_resolv_mutex);
272 if (request != NULL) {
275 if (rc != LDAP_SUCCESS && hostlist != NULL) {
280 return LDAP_NOT_SUPPORTED;
281 #endif /* HAVE_RES_QUERY */