]> git.sur5r.net Git - openldap/commitdiff
added referral support to back-{ldap,meta}; need to allow send_serch_reference()...
authorPierangelo Masarati <ando@openldap.org>
Sat, 31 Aug 2002 10:35:23 +0000 (10:35 +0000)
committerPierangelo Masarati <ando@openldap.org>
Sat, 31 Aug 2002 10:35:23 +0000 (10:35 +0000)
servers/slapd/back-ldap/search.c
servers/slapd/back-meta/search.c
servers/slapd/result.c

index a80de47198fda54e65b57ed200fcbe6c1473ef70..47f211c5da48b3c6908612d6ef1aa4d259bb98d5 100644 (file)
@@ -82,12 +82,23 @@ ldap_back_search(
 #endif /* ENABLE_REWRITE */
        struct slap_limits_set *limit = NULL;
        int isroot = 0;
+       BerVarray v2refs = NULL;
 
        lc = ldap_back_getconn(li, conn, op);
        if ( !lc ) {
                return( -1 );
        }
 
+       /*
+        * controls are set in ldap_back_dobind()
+        * 
+        * FIXME: in case of values return filter, we might want
+        * to map attrs and maybe rewrite value
+        */
+       if ( !ldap_back_dobind( lc, op ) ) {
+               return( -1 );
+       }
+
        /* if not root, get appropriate limits */
        if ( be_isroot( be, &op->o_ndn ) ) {
                isroot = 1;
@@ -104,8 +115,8 @@ ldap_back_search(
                        
                /* positive hard limit means abort */
                } else if ( limit->lms_t_hard > 0 ) {
-                       send_search_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
-                                       NULL, NULL, NULL, NULL, 0 );
+                       send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
+                                       NULL, NULL, NULL, NULL );
                        rc = 0;
                        goto finish;
                }
@@ -122,8 +133,8 @@ ldap_back_search(
                        
                /* positive hard limit means abort */
                } else if ( limit->lms_s_hard > 0 ) {
-                       send_search_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
-                                       NULL, NULL, NULL, NULL, 0 );
+                       send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
+                                       NULL, NULL, NULL, NULL );
                        rc = 0;
                        goto finish;
                }
@@ -131,6 +142,7 @@ ldap_back_search(
                /* negative hard limit means no limit */
        }
 
+       /* should we check return values? */
        if (deref != -1)
                ldap_set_option( lc->ld, LDAP_OPT_DEREF, (void *)&deref);
        if (tlimit != -1)
@@ -138,17 +150,6 @@ ldap_back_search(
        if (slimit != -1)
                ldap_set_option( lc->ld, LDAP_OPT_SIZELIMIT, (void *)&slimit);
 
-
-       /*
-        * controls are set in ldap_back_dobind()
-        * 
-        * FIXME: in case of values return filter, we might want
-        * to map attrs and maybe rewrite value
-        */
-       if ( !ldap_back_dobind( lc, op ) ) {
-               return( -1 );
-       }
-
        /*
         * Rewrite the search base, if required
         */
@@ -273,16 +274,61 @@ fail:;
                        rc = 0;
                        goto finish;
                }
+
                if (rc == 0) {
                        tv.tv_sec = 0;
                        tv.tv_usec = 100000;
                        ldap_pvt_thread_yield();
+
                } else if (rc == LDAP_RES_SEARCH_ENTRY) {
                        e = ldap_first_entry(lc->ld,res);
-                       if ( ldap_send_entry(be, op, lc, e, attrs, attrsonly) == LDAP_SUCCESS ) {
+                       if ( ldap_send_entry(be, op, lc, e, attrs, attrsonly) 
+                                       == LDAP_SUCCESS ) {
                                count++;
                        }
                        ldap_msgfree(res);
+
+               } else if ( rc == LDAP_RES_SEARCH_REFERENCE ) {
+                       char            **references = NULL;
+                       LDAPControl     **ctrls = NULL;
+                       BerVarray       refs;
+                       int             cnt;
+
+                       rc = ldap_parse_reference( lc->ld, res,
+                                       &references, &ctrls, 1 );
+
+                       if ( rc != LDAP_SUCCESS ) {
+                               continue;
+                       }
+
+                       if ( references == NULL ) {
+                               continue;
+                       }
+
+                       for ( cnt = 0; references[ cnt ]; cnt++ )
+                               /* NO OP */ ;
+                               
+                       refs = ch_calloc( cnt + 1, sizeof( struct berval ) );
+
+                       for ( cnt = 0; references[ cnt ]; cnt++ ) {
+                               refs[ cnt ].bv_val = references[ cnt ];
+                               refs[ cnt ].bv_len = strlen( references[ cnt ] );
+                       }
+
+                       /* ignore return value by now */
+                       ( void )send_search_reference( be, conn, op, 
+                                       NULL, refs, ctrls, &v2refs );
+
+                       /* cleanup */
+                       if ( references ) {
+                               ldap_value_free( references );
+                               ch_free( refs );
+                       }
+
+                       if ( ctrls ) {
+                               ldap_controls_free( ctrls );
+                       }
+
                } else {
                        sres = ldap_result2error(lc->ld, res, 1);
                        sres = ldap_back_map_result(sres);
@@ -328,12 +374,18 @@ fail:;
                }
        }
 
+       if ( v2refs ) {
+               sres = LDAP_REFERRAL;
+       }
        send_search_result( conn, op, sres,
-               mmatch, err, NULL, NULL, count );
+               mmatch, err, v2refs, NULL, count );
 
 #else /* !ENABLE_REWRITE */
+       if ( v2refs ) {
+               sres = LDAP_REFERRAL;
+       }
        send_search_result( conn, op, sres,
-               match, err, NULL, NULL, count );
+               match, err, v2refs, NULL, count );
 #endif /* !ENABLE_REWRITE */
 
 finish:;
index 4bab7a31f8fa9380fcb1fc6e7fe94a60b834cbef..0f6bce2dc73952084d09310812f6bb037c67de99 100644 (file)
@@ -123,6 +123,7 @@ meta_back_search(
        char *match = NULL, *err = NULL;
        char *mbase = NULL, *mmatch = NULL;
        struct berval mfilter;
+       BerVarray v2refs = NULL;
                
        int i, last = 0, candidates = 0, op_type;
        struct slap_limits_set *limit = NULL;
@@ -134,6 +135,12 @@ meta_back_search(
                op_type = META_OP_ALLOW_MULTIPLE;
        }
        
+       /*
+        * controls are set in ldap_back_dobind()
+        * 
+        * FIXME: in case of values return filter, we might want
+        * to map attrs and maybe rewrite value
+        */
        lc = meta_back_getconn( li, conn, op, op_type, nbase, NULL );
        if ( !lc || !meta_back_dobind( lc, op ) ) {
                return -1;
@@ -144,8 +151,8 @@ meta_back_search(
         */
        msgid = ch_calloc( sizeof( int ), li->ntargets );
        if ( msgid == NULL ) {
-               send_search_result( conn, op, LDAP_OTHER,
-                               NULL, NULL, NULL, NULL, 0 );
+               send_ldap_result( conn, op, LDAP_OTHER,
+                               NULL, NULL, NULL, NULL );
                return -1;
        }
        
@@ -165,8 +172,8 @@ meta_back_search(
                        
                /* positive hard limit means abort */
                } else if ( limit->lms_t_hard > 0 ) {
-                       send_search_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
-                                       NULL, NULL, NULL, NULL, 0 );
+                       send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
+                                       NULL, NULL, NULL, NULL );
                        rc = 0;
                        goto finish;
                }
@@ -183,8 +190,8 @@ meta_back_search(
                        
                /* positive hard limit means abort */
                } else if ( limit->lms_s_hard > 0 ) {
-                       send_search_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
-                                       NULL, NULL, NULL, NULL, 0 );
+                       send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
+                                       NULL, NULL, NULL, NULL );
                        rc = 0;
                        goto finish;
                }
@@ -205,6 +212,7 @@ meta_back_search(
                        continue;
                }
 
+               /* should we check return values? */
                if ( deref != -1 ) {
                        ldap_set_option( lsc->ld, LDAP_OPT_DEREF,
                                        ( void * )&deref);
@@ -288,15 +296,13 @@ meta_back_search(
                
                case REWRITE_REGEXEC_UNWILLING:
                        send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
-                                       NULL, "Unwilling to perform",
-                                       NULL, NULL );
+                                       NULL, NULL, NULL, NULL );
                        rc = -1;
                        goto finish;
 
                case REWRITE_REGEXEC_ERR:
                        send_ldap_result( conn, op, LDAP_OTHER,
-                                       NULL, "Rewrite error",
-                                       NULL, NULL );
+                                       NULL, NULL, NULL, NULL );
                        rc = -1;
                        goto finish;
                }
@@ -403,6 +409,9 @@ meta_back_search(
 
        /*
         * In case there are no candidates, no cycle takes place...
+        *
+        * FIXME: we might use a queue, to balance the load 
+        * among the candidates
         */
        for ( count = 0, rc = 0; candidates > 0; ) {
                int ab, gotit = 0;
@@ -424,25 +433,35 @@ meta_back_search(
                        if ( slimit > 0 && count == slimit ) {
                                send_search_result( conn, op,
                                                LDAP_SIZELIMIT_EXCEEDED,
-                                               NULL, NULL, NULL, NULL, count );
+                                               NULL, NULL, v2refs, NULL, 
+                                               count );
                                goto finish;
                        }
 
+                       /*
+                        * FIXME: handle time limit as well?
+                        * Note that target servers are likely 
+                        * to handle it, so at some time we'll
+                        * get a LDAP_TIMELIMIT_EXCEEDED from
+                        * one of them ...
+                        */
                        rc = ldap_result( lsc->ld, msgid[ i ],
                                        0, &tv, &res );
 
                        if ( rc == 0 ) {
                                continue;
+
                        } else if ( rc == -1 ) {
                                /* something REALLY bad happened! */
                                ( void )meta_clear_unused_candidates( li,
                                                lc, -1, 0 );
-                               send_search_result( conn, op,
-                                               LDAP_OTHER,
-                                               "", "", NULL, NULL, count );
+                               send_search_result( conn, op, LDAP_OTHER,
+                                               NULL, NULL, v2refs, NULL, 
+                                               count );
                                
                                /* anything else needs be done? */
                                goto finish;
+
                        } else if ( rc == LDAP_RES_SEARCH_ENTRY ) {
                                e = ldap_first_entry( lsc->ld, res );
                                if ( meta_send_entry( be, op, lc, i, e, attrs,
@@ -451,6 +470,53 @@ meta_back_search(
                                }
                                ldap_msgfree( res );
                                gotit = 1;
+
+                       } else if ( rc == LDAP_RES_SEARCH_REFERENCE ) {
+                               char            **references = NULL;
+                               LDAPControl     **ctrls = NULL;
+                               BerVarray       refs;
+                               int             cnt;
+
+                               /*
+                                * FIXME: should we collect references
+                                * and send them alltogether at the end?
+                                */
+
+                               rc = ldap_parse_reference( lsc->ld, res,
+                                               &references, &ctrls, 1 );
+
+                               if ( rc != LDAP_SUCCESS ) {
+                                       continue;
+                               }
+
+                               if ( references == NULL ) {
+                                       continue;
+                               }
+
+                               for ( cnt = 0; references[ cnt ]; cnt++ )
+                                       /* NO OP */ ;
+                               
+                               refs = ch_calloc( cnt + 1, sizeof( struct berval ) );
+
+                               for ( cnt = 0; references[ cnt ]; cnt++ ) {
+                                       refs[ cnt ].bv_val = references[ cnt ];
+                                       refs[ cnt ].bv_len = strlen( references[ cnt ] );
+                               }
+
+                               /* ignore return value by now */
+                               ( void )send_search_reference( be, conn, op, 
+                                               NULL, refs, ctrls, &v2refs );
+
+                               /* cleanup */
+                               if ( references ) {
+                                       ldap_value_free( references );
+                                       ch_free( refs );
+                               }
+
+                               if ( ctrls ) {
+                                       ldap_controls_free( ctrls );
+                               }
+
                        } else {
                                sres = ldap_result2error( lsc->ld,
                                                res, 1 );
@@ -548,8 +614,17 @@ meta_back_search(
                }
        }
 
-       send_search_result( conn, op, sres,
-               mmatch, err, NULL, NULL, count );
+       /*
+        * In case we returned at least one entry, we return LDAP_SUCCESS
+        * otherwise, the latter error code we got
+        *
+        * FIXME: we should handle error codes and return the more 
+        * important/reasonable
+        */
+       if ( sres == LDAP_SUCCESS && v2refs ) {
+               sres = LDAP_REFERRAL;
+       }
+       send_search_result( conn, op, sres, mmatch, err, v2refs, NULL, count );
 
 finish:;
        if ( match ) {
index ed5f85f7824a8fd5ca88cc1092e8f5f02b3fe515..863547f206b5646e73b1ffa940486d68ef557151 100644 (file)
@@ -1207,21 +1207,22 @@ send_search_reference(
 #ifdef NEW_LOGGING
        LDAP_LOG( OPERATION, ENTRY, 
                "send_search_reference: conn %lu  dn=\"%s\"\n", 
-               op->o_connid, e->e_dn, 0 );
+               op->o_connid, e ? e->e_dn : "(null)", 0 );
 #else
        Debug( LDAP_DEBUG_TRACE,
                "=> send_search_reference: dn=\"%s\"\n",
-               e->e_dn, 0, 0 );
+               e ? e->e_dn : "(null)", 0, 0 );
 #endif
 
 
-       if ( ! access_allowed( be, conn, op, e,
+       if (  e && ! access_allowed( be, conn, op, e,
                ad_entry, NULL, ACL_READ, NULL ) )
        {
 #ifdef NEW_LOGGING
                LDAP_LOG( ACL, INFO, 
                        "send_search_reference: conn %lu        "
-                       "access to entry %s not allowed\n", op->o_connid, e->e_dn, 0 );
+                       "access to entry %s not allowed\n",
+                       op->o_connid, e->e_dn, 0 );
 #else
                Debug( LDAP_DEBUG_ACL,
                        "send_search_reference: access to entry not allowed\n",
@@ -1231,7 +1232,7 @@ send_search_reference(
                return( 1 );
        }
 
-       if ( ! access_allowed( be, conn, op, e,
+       if ( e && ! access_allowed( be, conn, op, e,
                ad_ref, NULL, ACL_READ, NULL ) )
        {
 #ifdef NEW_LOGGING
@@ -1252,11 +1253,11 @@ send_search_reference(
 #ifdef NEW_LOGGING
                LDAP_LOG( OPERATION, ERR, 
                        "send_search_reference: conn %lu null ref in (%s).\n",
-                       op->o_connid, e->e_dn, 0 );
+                       op->o_connid, e ? e->e_dn : "(null)", 0 );
 #else
                Debug( LDAP_DEBUG_ANY,
                        "send_search_reference: null ref in (%s)\n", 
-                       e->e_dn, 0, 0 );
+                       e ? e->e_dn : "(null)", 0, 0 );
 #endif
 
                return( 1 );
@@ -1310,7 +1311,7 @@ send_search_reference(
        ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
 
        Statslog( LDAP_DEBUG_STATS2, "conn=%lu op=%lu REF dn=\"%s\"\n",
-               conn->c_connid, op->o_opid, e->e_dn, 0, 0 );
+               conn->c_connid, op->o_opid, e ? e->e_dn : "(null)", 0, 0 );
 
 #ifdef NEW_LOGGING
        LDAP_LOG( OPERATION, ENTRY,