3 * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
8 * locate using DNS SRV records. Location code based on
9 * 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. */
36 int ldap_pvt_domain2dn(LDAP_CONST char *domain_in, char **dnp)
38 char *domain, *s, *tok_r, *dn;
41 if (domain_in == NULL || dnp == NULL) {
42 return LDAP_NO_MEMORY;
44 domain = LDAP_STRDUP(domain_in);
46 return LDAP_NO_MEMORY;
51 for (s = ldap_pvt_strtok(domain, ".", &tok_r);
53 s = ldap_pvt_strtok(NULL, ".", &tok_r)) {
54 size_t len = strlen(s);
56 dn = (char *) LDAP_REALLOC(dn, loc + len + 4);
59 return LDAP_NO_MEMORY;
63 strcpy(dn + loc, ",");
66 strcpy(dn + loc, "dc=");
81 * Lookup LDAP servers for domain (using the DNS
82 * SRV record _ldap._tcp.domain), set the default
83 * base using an algorithmic mapping of the domain,
84 * and return a session.
86 int ldap_dnssrv_init(LDAP ** ldp, LDAP_CONST char *domain)
88 #ifdef HAVE_RES_SEARCH
91 char *hostlist = NULL;
94 unsigned char reply[1024];
96 request = LDAP_MALLOC(strlen(domain) + sizeof("_ldap._tcp."));
97 if (request == NULL) {
101 sprintf(request, "_ldap._tcp.%s", domain);
103 #ifdef LDAP_R_COMPILE
104 ldap_pvt_thread_mutex_lock(&ldap_int_resolv_mutex);
107 len = res_search(request, C_IN, T_SRV, reply, sizeof(reply));
113 int priority, weight;
115 /* Parse out query */
118 status = dn_expand(reply, reply + len, p, host, sizeof(host));
125 while (p < reply + len) {
126 int type, class, ttl, size;
127 status = dn_expand(reply, reply + len, p, host, sizeof(host));
132 type = (p[0] << 8) | p[1];
134 class = (p[0] << 8) | p[1];
136 ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
138 size = (p[0] << 8) | p[1];
142 status = dn_expand(reply, reply + len, p + 6, host, sizeof(host));
146 priority = (p[0] << 8) | p[1];
147 weight = (p[2] << 8) | p[3];
148 port = (p[4] << 8) | p[5];
150 buflen = strlen(host) + /* :XXXXX\0 */ 7;
151 hostlist = (char *) LDAP_REALLOC(hostlist, cur + buflen);
152 if (hostlist == NULL) {
157 /* not first time around */
158 hostlist[cur++] = ' ';
160 cur += sprintf(&hostlist[cur], "%s:%hd", host, port);
165 if (hostlist == NULL) {
166 /* No LDAP servers found in DNS. */
167 rc = LDAP_UNAVAILABLE;
170 rc = ldap_create(&ld);
171 if (rc != LDAP_SUCCESS) {
174 rc = ldap_set_option(ld, LDAP_OPT_HOST_NAME, hostlist);
175 if (rc != LDAP_SUCCESS) {
178 rc = ldap_pvt_domain2dn(domain, &dn);
179 if (rc != LDAP_SUCCESS) {
182 if (ld->ld_options.ldo_defbase != NULL) {
183 LDAP_FREE(ld->ld_options.ldo_defbase);
185 ld->ld_options.ldo_defbase = dn;
192 #ifdef LDAP_R_COMPILE
193 ldap_pvt_thread_mutex_unlock(&ldap_int_resolv_mutex);
196 if (request != NULL) {
199 if (hostlist != NULL) {
202 if (rc != LDAP_SUCCESS && ld != NULL) {
203 ldap_ld_free(ld, 1, NULL, NULL);
207 return LDAP_NOT_SUPPORTED;
208 #endif /* HAVE_RES_SEARCH */