]> git.sur5r.net Git - openldap/blobdiff - libraries/libldap/dnssrv.c
Merge remote branch 'origin/mdb.master' into OPENLDAP_REL_ENG_2_4
[openldap] / libraries / libldap / dnssrv.c
index 94875c00ed3a69cd8c1af53a650284778d165727..74569f3147361c7d5aaea2f53c2025a18d3bf0f7 100644 (file)
@@ -1,7 +1,16 @@
 /* $OpenLDAP$ */
-/*
- * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
- * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2012 The OpenLDAP Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
  */
 
 /*
 #include <resolv.h>
 #endif
 
-/* Sometimes this is not defined. */
-#ifndef T_SRV
-#define T_SRV            33
-#endif                         /* T_SRV */
-
 int ldap_dn2domain(
        LDAP_CONST char *dn_in,
        char **domainp)
 {
-       int i;
-       char *domain = NULL;
-       char **dn;
+       int i, j;
+       char *ndomain;
+       LDAPDN dn = NULL;
+       LDAPRDN rdn = NULL;
+       LDAPAVA *ava = NULL;
+       struct berval domain = BER_BVNULL;
+       static const struct berval DC = BER_BVC("DC");
+       static const struct berval DCOID = BER_BVC("0.9.2342.19200300.100.1.25");
 
-       if( dn_in == NULL || domainp == NULL ) {
-               return -1;
-       }
+       assert( dn_in != NULL );
+       assert( domainp != NULL );
 
-       dn = ldap_explode_dn( dn_in, 0 );
+       *domainp = NULL;
 
-       if( dn == NULL ) {
+       if ( ldap_str2dn( dn_in, &dn, LDAP_DN_FORMAT_LDAP ) != LDAP_SUCCESS ) {
                return -2;
        }
 
-       for( i=0; dn[i] != NULL; i++ ) {
-               char ** rdn = ldap_explode_rdn( dn[i], 0 );
-
-               if( rdn == NULL || *rdn == NULL ) {
-                       LDAP_FREE( rdn );
-                       LDAP_FREE( domain );
-                       LDAP_VFREE( dn );
-                       return -3;
-               }
-
+       if( dn ) for( i=0; dn[i] != NULL; i++ ) {
+               rdn = dn[i];
 
-               if( rdn[1] == NULL ) {
-                       /*
-                        * single-valued RDN
-                        */
-                       char *dc;
+               for( j=0; rdn[j] != NULL; j++ ) {
+                       ava = rdn[j];
 
-#define LDAP_DC "dc="
-#define LDAP_DCOID "0.9.2342.19200300.100.1.25="
-
-                       if( strncasecmp( rdn[0],
-                               LDAP_DC, sizeof(LDAP_DC)-1 ) == 0 )
+                       if( rdn[j+1] == NULL &&
+                               (ava->la_flags & LDAP_AVA_STRING) &&
+                               ava->la_value.bv_len &&
+                               ( ber_bvstrcasecmp( &ava->la_attr, &DC ) == 0
+                               || ber_bvcmp( &ava->la_attr, &DCOID ) == 0 ) )
                        {
-                               dc = &rdn[0][sizeof(LDAP_DC)-1];
+                               if( domain.bv_len == 0 ) {
+                                       ndomain = LDAP_REALLOC( domain.bv_val,
+                                               ava->la_value.bv_len + 1);
 
-                       } else if( strncmp( rdn[0],
-                               LDAP_DCOID, sizeof(LDAP_DCOID)-1 ) == 0 )
-                       {
-                               dc = &rdn[0][sizeof(LDAP_DCOID)-1];
+                                       if( ndomain == NULL ) {
+                                               goto return_error;
+                                       }
 
-                       } else {
-                               dc = NULL;
-                       }
+                                       domain.bv_val = ndomain;
 
-                       if( dc != NULL ) {
-                               char *ndomain;
+                                       AC_MEMCPY( domain.bv_val, ava->la_value.bv_val,
+                                               ava->la_value.bv_len );
 
-                               if( *dc == '\0' ) {
-                                       /* dc value is empty! */
-                                       LDAP_FREE( rdn );
-                                       LDAP_FREE( domain );
-                                       LDAP_VFREE( dn );
-                                       LDAP_VFREE( rdn );
-                                       return -4;
-                               }
+                                       domain.bv_len = ava->la_value.bv_len;
+                                       domain.bv_val[domain.bv_len] = '\0';
 
-                               ndomain = LDAP_REALLOC( domain,
-                                       ( domain == NULL ? 0 : strlen(domain) )
-                                       + strlen(dc) + sizeof(".") );
+                               } else {
+                                       ndomain = LDAP_REALLOC( domain.bv_val,
+                                               ava->la_value.bv_len + sizeof(".") + domain.bv_len );
 
-                               if( ndomain == NULL ) {
-                                       LDAP_FREE( rdn );
-                                       LDAP_FREE( domain );
-                                       LDAP_VFREE( dn );
-                                       LDAP_VFREE( rdn );
-                                       return -5;
-                               }
-
-                               if( domain == NULL ) ndomain[0] = '\0';
-
-                               strcat( ndomain, dc );
-                               strcat( ndomain, "." );
+                                       if( ndomain == NULL ) {
+                                               goto return_error;
+                                       }
 
-                               domain = ndomain;
-                               continue;
+                                       domain.bv_val = ndomain;
+                                       domain.bv_val[domain.bv_len++] = '.';
+                                       AC_MEMCPY( &domain.bv_val[domain.bv_len],
+                                               ava->la_value.bv_val, ava->la_value.bv_len );
+                                       domain.bv_len += ava->la_value.bv_len;
+                                       domain.bv_val[domain.bv_len] = '\0';
+                               }
+                       } else {
+                               domain.bv_len = 0;
                        }
-               }
-
-               /*
-                * multi-valued RDN or fall thru
-                */
+               } 
+       }
 
-               LDAP_VFREE( rdn );
-               LDAP_FREE( domain );
-               domain = NULL;
-       } 
 
-       if( domain != NULL &&  *domain == '\0' ) {
-               LDAP_FREE( domain );
-               domain = NULL;
+       if( domain.bv_len == 0 && domain.bv_val != NULL ) {
+               LDAP_FREE( domain.bv_val );
+               domain.bv_val = NULL;
        }
 
-       *domainp = domain;
+       ldap_dnfree( dn );
+       *domainp = domain.bv_val;
        return 0;
+
+return_error:
+       ldap_dnfree( dn );
+       LDAP_FREE( domain.bv_val );
+       return -1;
 }
 
 int ldap_domain2dn(
        LDAP_CONST char *domain_in,
        char **dnp)
 {
-    char *domain, *s, *tok_r, *dn;
-    size_t loc;
+       char *domain, *s, *tok_r, *dn, *dntmp;
+       size_t loc;
 
-    if (domain_in == NULL || dnp == NULL) {
-       return LDAP_NO_MEMORY;
-    }
-    domain = LDAP_STRDUP(domain_in);
-    if (domain == NULL) {
-       return LDAP_NO_MEMORY;
-    }
-    dn = NULL;
-    loc = 0;
-
-    for (s = ldap_pvt_strtok(domain, ".", &tok_r);
-        s != NULL;
-        s = ldap_pvt_strtok(NULL, ".", &tok_r)) {
-       size_t len = strlen(s);
-
-       dn = (char *) LDAP_REALLOC(dn, loc + sizeof(",dc=") + len );
-       if (dn == NULL) {
-           LDAP_FREE(domain);
-           return LDAP_NO_MEMORY;
-       }
-       if (loc > 0) {
-           /* not first time. */
-           strcpy(dn + loc, ",");
-           loc++;
+       assert( domain_in != NULL );
+       assert( dnp != NULL );
+
+       domain = LDAP_STRDUP(domain_in);
+       if (domain == NULL) {
+               return LDAP_NO_MEMORY;
        }
-       strcpy(dn + loc, "dc=");
-       loc += sizeof("dc=")-1;
+       dn = NULL;
+       loc = 0;
+
+       for (s = ldap_pvt_strtok(domain, ".", &tok_r);
+               s != NULL;
+               s = ldap_pvt_strtok(NULL, ".", &tok_r))
+       {
+               size_t len = strlen(s);
+
+               dntmp = (char *) LDAP_REALLOC(dn, loc + sizeof(",dc=") + len );
+               if (dntmp == NULL) {
+                   if (dn != NULL)
+                       LDAP_FREE(dn);
+                   LDAP_FREE(domain);
+                   return LDAP_NO_MEMORY;
+               }
 
-       strcpy(dn + loc, s);
-       loc += len;
-    }
+               dn = dntmp;
 
-    LDAP_FREE(domain);
+               if (loc > 0) {
+                   /* not first time. */
+                   strcpy(dn + loc, ",");
+                   loc++;
+               }
+               strcpy(dn + loc, "dc=");
+               loc += sizeof("dc=")-1;
 
-    *dnp = dn;
+               strcpy(dn + loc, s);
+               loc += len;
+    }
 
-    return LDAP_SUCCESS;
+       LDAP_FREE(domain);
+       *dnp = dn;
+       return LDAP_SUCCESS;
 }
 
 /*
@@ -191,44 +182,64 @@ int ldap_domain2hostlist(
        LDAP_CONST char *domain,
        char **list )
 {
-#ifdef HAVE_RES_SEARCH
+#ifdef HAVE_RES_QUERY
+#define DNSBUFSIZ (64*1024)
     char *request;
-    char *dn;
     char *hostlist = NULL;
     int rc, len, cur = 0;
-    unsigned char reply[1024];
+    unsigned char reply[DNSBUFSIZ];
 
-       if( domain == NULL || *domain == '\0' ) {
-               return LDAP_PARAM_ERROR;
-       }
+       assert( domain != NULL );
+       assert( list != NULL );
 
-       if( list == NULL ) {
+       if( *domain == '\0' ) {
                return LDAP_PARAM_ERROR;
        }
 
     request = LDAP_MALLOC(strlen(domain) + sizeof("_ldap._tcp."));
     if (request == NULL) {
-       rc = LDAP_NO_MEMORY;
-       goto out;
+               return LDAP_NO_MEMORY;
     }
     sprintf(request, "_ldap._tcp.%s", domain);
 
-#ifdef LDAP_R_COMPILE
-    ldap_pvt_thread_mutex_lock(&ldap_int_resolv_mutex);
-#endif
+    LDAP_MUTEX_LOCK(&ldap_int_resolv_mutex);
 
     rc = LDAP_UNAVAILABLE;
-    len = res_search(request, C_IN, T_SRV, reply, sizeof(reply));
+#ifdef NS_HFIXEDSZ
+       /* Bind 8/9 interface */
+    len = res_query(request, ns_c_in, ns_t_srv, reply, sizeof(reply));
+#      ifndef T_SRV
+#              define T_SRV ns_t_srv
+#      endif
+#else
+       /* Bind 4 interface */
+#      ifndef T_SRV
+#              define T_SRV 33
+#      endif
+
+    len = res_query(request, C_IN, T_SRV, reply, sizeof(reply));
+#endif
     if (len >= 0) {
        unsigned char *p;
-       char host[1024];
+       char host[DNSBUFSIZ];
        int status;
        u_short port;
        /* int priority, weight; */
 
        /* Parse out query */
        p = reply;
+
+#ifdef NS_HFIXEDSZ
+       /* Bind 8/9 interface */
+       p += NS_HFIXEDSZ;
+#elif defined(HFIXEDSZ)
+       /* Bind 4 interface w/ HFIXEDSZ */
+       p += HFIXEDSZ;
+#else
+       /* Bind 4 interface w/o HFIXEDSZ */
        p += sizeof(HEADER);
+#endif
+
        status = dn_expand(reply, reply + len, p, host, sizeof(host));
        if (status < 0) {
            goto out;
@@ -262,8 +273,12 @@ int ldap_domain2hostlist(
                /* weight = (p[2] << 8) | p[3]; */
                port = (p[4] << 8) | p[5];
 
-               buflen = strlen(host) + sizeof(":65355");
-               hostlist = (char *) LDAP_REALLOC(hostlist, cur + buflen);
+               if ( port == 0 || host[ 0 ] == '\0' ) {
+                   goto add_size;
+               }
+
+               buflen = strlen(host) + STRLENOF(":65355 ");
+               hostlist = (char *) LDAP_REALLOC(hostlist, cur + buflen + 1);
                if (hostlist == NULL) {
                    rc = LDAP_NO_MEMORY;
                    goto out;
@@ -272,8 +287,9 @@ int ldap_domain2hostlist(
                    /* not first time around */
                    hostlist[cur++] = ' ';
                }
-               cur += sprintf(&hostlist[cur], "%s:%hd", host, port);
+               cur += sprintf(&hostlist[cur], "%s:%hu", host, port);
            }
+add_size:;
            p += size;
        }
     }
@@ -287,9 +303,7 @@ int ldap_domain2hostlist(
        *list = hostlist;
 
   out:
-#ifdef LDAP_R_COMPILE
-    ldap_pvt_thread_mutex_unlock(&ldap_int_resolv_mutex);
-#endif
+    LDAP_MUTEX_UNLOCK(&ldap_int_resolv_mutex);
 
     if (request != NULL) {
        LDAP_FREE(request);
@@ -300,5 +314,5 @@ int ldap_domain2hostlist(
     return rc;
 #else
     return LDAP_NOT_SUPPORTED;
-#endif                         /* HAVE_RES_SEARCH */
+#endif /* HAVE_RES_QUERY */
 }