Back to index

openldap  2.4.31
Functions
ldap_sync.c File Reference
#include "portable.h"
#include <ac/time.h>
#include "ldap-int.h"

Go to the source code of this file.

Functions

ldap_sync_tldap_sync_initialize (ldap_sync_t *ls_in)
void ldap_sync_destroy (ldap_sync_t *ls, int freeit)
static int ldap_sync_search_entry (ldap_sync_t *ls, LDAPMessage *res)
static int ldap_sync_search_reference (ldap_sync_t *ls, LDAPMessage *res)
static int ldap_sync_search_result (ldap_sync_t *ls, LDAPMessage *res)
static int ldap_sync_search_intermediate (ldap_sync_t *ls, LDAPMessage *res, int *refreshDone)
int ldap_sync_init (ldap_sync_t *ls, int mode)
int ldap_sync_init_refresh_only (ldap_sync_t *ls)
int ldap_sync_init_refresh_and_persist (ldap_sync_t *ls)
int ldap_sync_poll (ldap_sync_t *ls)

Function Documentation

void ldap_sync_destroy ( ldap_sync_t ls,
int  freeit 
)

Definition at line 82 of file ldap_sync.c.

{
       assert( ls != NULL );

       if ( ls->ls_base != NULL ) {
              ldap_memfree( ls->ls_base );
              ls->ls_base = NULL;
       }

       if ( ls->ls_filter != NULL ) {
              ldap_memfree( ls->ls_filter );
              ls->ls_filter = NULL;
       }

       if ( ls->ls_attrs != NULL ) {
              int    i;

              for ( i = 0; ls->ls_attrs[ i ] != NULL; i++ ) {
                     ldap_memfree( ls->ls_attrs[ i ] );
              }
              ldap_memfree( ls->ls_attrs );
              ls->ls_attrs = NULL;
       }

       if ( ls->ls_ld != NULL ) {
              (void)ldap_unbind_ext( ls->ls_ld, NULL, NULL );
#ifdef LDAP_SYNC_TRACE
              fprintf( stderr, "ldap_unbind_ext()\n" );
#endif /* LDAP_SYNC_TRACE */
              ls->ls_ld = NULL;
       }

       if ( ls->ls_cookie.bv_val != NULL ) {
              ldap_memfree( ls->ls_cookie.bv_val );
              ls->ls_cookie.bv_val = NULL;
       }

       if ( freeit ) {
              ldap_memfree( ls );
       }
}

Here is the call graph for this function:

int ldap_sync_init ( ldap_sync_t ls,
int  mode 
)

Definition at line 653 of file ldap_sync.c.

{
       LDAPControl   ctrl = { 0 },
                     *ctrls[ 2 ];
       BerElement    *ber = NULL;
       int           rc;
       struct timeval       tv = { 0 },
                     *tvp = NULL;
       LDAPMessage   *res = NULL;

#ifdef LDAP_SYNC_TRACE
       fprintf( stderr, "ldap_sync_init(%s)...\n",
              mode == LDAP_SYNC_REFRESH_AND_PERSIST ?
                     "LDAP_SYNC_REFRESH_AND_PERSIST" :
                     ( mode == LDAP_SYNC_REFRESH_ONLY ? 
                            "LDAP_SYNC_REFRESH_ONLY" : "unknown" ) );
#endif /* LDAP_SYNC_TRACE */

       assert( ls != NULL );
       assert( ls->ls_ld != NULL );

       /* support both refreshOnly and refreshAndPersist */
       switch ( mode ) {
       case LDAP_SYNC_REFRESH_AND_PERSIST:
       case LDAP_SYNC_REFRESH_ONLY:
              break;

       default:
              fprintf( stderr, "ldap_sync_init: unknown mode=%d\n", mode );
              return LDAP_PARAM_ERROR;
       }

       /* check consistency of cookie and reloadHint at initial refresh */
       if ( ls->ls_cookie.bv_val == NULL && ls->ls_reloadHint != 0 ) {
              fprintf( stderr, "ldap_sync_init: inconsistent cookie/rhint\n" );
              return LDAP_PARAM_ERROR;
       }

       ctrls[ 0 ] = &ctrl;
       ctrls[ 1 ] = NULL;

       /* prepare the Sync Request control */
       ber = ber_alloc_t( LBER_USE_DER );
#ifdef LDAP_SYNC_TRACE
       fprintf( stderr, "%sber_alloc_t() %s= NULL\n",
              ber == NULL ? "!!! " : "",
              ber == NULL ? "=" : "!" );
#endif /* LDAP_SYNC_TRACE */
       if ( ber == NULL ) {
              rc = LDAP_NO_MEMORY;
              goto done;
       }

       ls->ls_refreshPhase = LDAP_SYNC_CAPI_NONE;

       if ( ls->ls_cookie.bv_val != NULL ) {
              ber_printf( ber, "{eOb}", mode,
                     &ls->ls_cookie, ls->ls_reloadHint );

       } else {
              ber_printf( ber, "{eb}", mode, ls->ls_reloadHint );
       }

       rc = ber_flatten2( ber, &ctrl.ldctl_value, 0 );
#ifdef LDAP_SYNC_TRACE
       fprintf( stderr,
              "%sber_flatten2() == %d\n",
              rc ? "!!! " : "",
              rc );
#endif /* LDAP_SYNC_TRACE */
       if ( rc < 0 ) {
              rc = LDAP_OTHER;
                goto done;
        }

       /* make the control critical, as we cannot proceed without */
       ctrl.ldctl_oid = LDAP_CONTROL_SYNC;
       ctrl.ldctl_iscritical = 1;

       /* timelimit? */
       if ( ls->ls_timelimit ) {
              tv.tv_sec = ls->ls_timelimit;
              tvp = &tv;
       }

       /* actually run the search */
       rc = ldap_search_ext( ls->ls_ld,
              ls->ls_base, ls->ls_scope, ls->ls_filter,
              ls->ls_attrs, 0, ctrls, NULL,
              tvp, ls->ls_sizelimit, &ls->ls_msgid );
#ifdef LDAP_SYNC_TRACE
       fprintf( stderr,
              "%sldap_search_ext(\"%s\", %d, \"%s\") == %d\n",
              rc ? "!!! " : "",
              ls->ls_base, ls->ls_scope, ls->ls_filter, rc );
#endif /* LDAP_SYNC_TRACE */
       if ( rc != LDAP_SUCCESS ) {
              goto done;
       }

       /* initial content/content update phase */
       for ( ; ; ) {
              LDAPMessage   *msg = NULL;

              /* NOTE: this very short timeout is just to let
               * ldap_result() yield long enough to get something */
              tv.tv_sec = 0;
              tv.tv_usec = 100000;

              rc = ldap_result( ls->ls_ld, ls->ls_msgid,
                     LDAP_MSG_RECEIVED, &tv, &res );
#ifdef LDAP_SYNC_TRACE
              fprintf( stderr,
                     "\t%sldap_result(%d) == %d\n",
                     rc == -1 ? "!!! " : "",
                     ls->ls_msgid, rc );
#endif /* LDAP_SYNC_TRACE */
              switch ( rc ) {
              case 0:
                     /*
                      * timeout
                      *
                      * TODO: can do something else in the meanwhile)
                      */
                     break;

              case -1:
                     /* smtg bad! */
                     goto done;

              default:
                     for ( msg = ldap_first_message( ls->ls_ld, res );
                            msg != NULL;
                            msg = ldap_next_message( ls->ls_ld, msg ) )
                     {
                            int    refreshDone;

                            switch ( ldap_msgtype( msg ) ) {
                            case LDAP_RES_SEARCH_ENTRY:
                                   rc = ldap_sync_search_entry( ls, res );
                                   break;

                            case LDAP_RES_SEARCH_REFERENCE:
                                   rc = ldap_sync_search_reference( ls, res );
                                   break;

                            case LDAP_RES_SEARCH_RESULT:
                                   rc = ldap_sync_search_result( ls, res );
                                   goto done_search;

                            case LDAP_RES_INTERMEDIATE:
                                   rc = ldap_sync_search_intermediate( ls, res, &refreshDone );
                                   if ( rc != LDAP_SUCCESS || refreshDone ) {
                                          goto done_search;
                                   }
                                   break;

                            default:
#ifdef LDAP_SYNC_TRACE
                                   fprintf( stderr, "\tgot something unexpected...\n" );
#endif /* LDAP_SYNC_TRACE */

                                   ldap_msgfree( res );

                                   rc = LDAP_OTHER;
                                   goto done;
                            }
                     }
                     ldap_msgfree( res );
                     res = NULL;
                     break;
              }
       }

done_search:;
       ldap_msgfree( res );

done:;
       if ( ber != NULL ) {
              ber_free( ber, 1 );
       }

       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 851 of file ldap_sync.c.

Here is the call graph for this function:

Definition at line 842 of file ldap_sync.c.

Here is the call graph for this function:

Definition at line 58 of file ldap_sync.c.

{
       ldap_sync_t   *ls = ls_in;

       if ( ls == NULL ) {
              ls = ldap_memalloc( sizeof( ldap_sync_t ) );
              if ( ls == NULL ) {
                     return NULL;
              }

       } else {
              memset( ls, 0, sizeof( ldap_sync_t ) );
       }

       ls->ls_scope = LDAP_SCOPE_SUBTREE;
       ls->ls_timeout = -1;

       return ls;
}

Here is the call graph for this function:

Definition at line 860 of file ldap_sync.c.

{
       struct timeval              tv,
                            *tvp = NULL;
       LDAPMessage          *res = NULL,
                            *msg;
       int                  rc = 0;

#ifdef LDAP_SYNC_TRACE
       fprintf( stderr, "ldap_sync_poll...\n" );
#endif /* LDAP_SYNC_TRACE */

       assert( ls != NULL );
       assert( ls->ls_ld != NULL );

       if ( ls->ls_timeout != -1 ) {
              tv.tv_sec = ls->ls_timeout;
              tv.tv_usec = 0;
              tvp = &tv;
       }

       rc = ldap_result( ls->ls_ld, ls->ls_msgid,
              LDAP_MSG_RECEIVED, tvp, &res );
       if ( rc <= 0 ) {
              return rc;
       }

       for ( msg = ldap_first_message( ls->ls_ld, res );
              msg;
              msg = ldap_next_message( ls->ls_ld, msg ) )
       {
              int    refreshDone;

              switch ( ldap_msgtype( msg ) ) {
              case LDAP_RES_SEARCH_ENTRY:
                     rc = ldap_sync_search_entry( ls, res );
                     break;

              case LDAP_RES_SEARCH_REFERENCE:
                     rc = ldap_sync_search_reference( ls, res );
                     break;

              case LDAP_RES_SEARCH_RESULT:
                     rc = ldap_sync_search_result( ls, res );
                     goto done_search;

              case LDAP_RES_INTERMEDIATE:
                     rc = ldap_sync_search_intermediate( ls, res, &refreshDone );
                     if ( rc != LDAP_SUCCESS || refreshDone ) {
                            goto done_search;
                     }
                     break;

              default:
#ifdef LDAP_SYNC_TRACE
                     fprintf( stderr, "\tgot something unexpected...\n" );
#endif /* LDAP_SYNC_TRACE */

                     ldap_msgfree( res );

                     rc = LDAP_OTHER;
                     goto done;
              }
       }

done_search:;
       ldap_msgfree( res );

done:;
       return rc;
}

Here is the call graph for this function:

static int ldap_sync_search_entry ( ldap_sync_t ls,
LDAPMessage *  res 
) [static]

Definition at line 128 of file ldap_sync.c.

{
       LDAPControl          **ctrls = NULL;
       int                  rc = LDAP_OTHER,
                            i;
       BerElement           *ber = NULL;
       struct berval        entryUUID = { 0 },
                            cookie = { 0 };
       int                  state = -1;
       ber_len_t            len;
       ldap_sync_refresh_t  phase;

#ifdef LDAP_SYNC_TRACE
       fprintf( stderr, "\tgot LDAP_RES_SEARCH_ENTRY\n" );
#endif /* LDAP_SYNC_TRACE */

       assert( ls != NULL );
       assert( res != NULL );

       phase = ls->ls_refreshPhase;

       /* OK */

       /* extract:
        * - data
        * - entryUUID
        *
        * check that:
        * - Sync State Control is "add"
        */

       /* the control MUST be present */

       /* extract controls */
       ldap_get_entry_controls( ls->ls_ld, res, &ctrls );
       if ( ctrls == NULL ) {
              goto done;
       }

       /* lookup the sync state control */
       for ( i = 0; ctrls[ i ] != NULL; i++ ) {
              if ( strcmp( ctrls[ i ]->ldctl_oid, LDAP_CONTROL_SYNC_STATE ) == 0 ) {
                     break;
              }
       }

       /* control must be present; there might be other... */
       if ( ctrls[ i ] == NULL ) {
              goto done;
       }

       /* extract data */
       ber = ber_init( &ctrls[ i ]->ldctl_value );
       if ( ber == NULL ) {
              goto done;
       }
       /* scan entryUUID in-place ("m") */
       if ( ber_scanf( ber, "{em" /*"}"*/, &state, &entryUUID ) == LBER_ERROR
              || entryUUID.bv_len == 0 )
       {
              goto done;
       }

       if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) {
              /* scan cookie in-place ("m") */
              if ( ber_scanf( ber, /*"{"*/ "m}", &cookie ) == LBER_ERROR ) {
                     goto done;
              }
              if ( cookie.bv_val != NULL ) {
                     ber_bvreplace( &ls->ls_cookie, &cookie );
              }
#ifdef LDAP_SYNC_TRACE
              fprintf( stderr, "\t\tgot cookie=%s\n",
                     cookie.bv_val ? cookie.bv_val : "(null)" );
#endif /* LDAP_SYNC_TRACE */
       }

       switch ( state ) {
       case LDAP_SYNC_PRESENT:
       case LDAP_SYNC_DELETE:
       case LDAP_SYNC_ADD:
       case LDAP_SYNC_MODIFY:
              /* NOTE: ldap_sync_refresh_t is defined
               * as the corresponding LDAP_SYNC_*
               * for the 4 above cases */
              phase = state;
#ifdef LDAP_SYNC_TRACE
              fprintf( stderr, "\t\tgot syncState=%s\n", ldap_sync_state2str( state ) );
#endif /* LDAP_SYNC_TRACE */
              break;

       default:
#ifdef LDAP_SYNC_TRACE
              fprintf( stderr, "\t\tgot unknown syncState=%d\n", state );
#endif /* LDAP_SYNC_TRACE */
              goto done;
       }

       rc = ls->ls_search_entry
              ? ls->ls_search_entry( ls, res, &entryUUID, phase )
              : LDAP_SUCCESS;

done:;
       if ( ber != NULL ) {
              ber_free( ber, 1 );
       }

       if ( ctrls != NULL ) {
              ldap_controls_free( ctrls );
       }

       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ldap_sync_search_intermediate ( ldap_sync_t ls,
LDAPMessage *  res,
int refreshDone 
) [static]

Definition at line 423 of file ldap_sync.c.

{
       int                  rc;
       char                 *retoid = NULL;
        struct berval              *retdata = NULL;
       BerElement           *ber = NULL;
       ber_len_t            len;
       ber_tag_t            syncinfo_tag;
       struct berval        cookie;
       int                  refreshDeletes = 0;
       BerVarray            syncUUIDs = NULL;
       ldap_sync_refresh_t  phase;

#ifdef LDAP_SYNC_TRACE
       fprintf( stderr, "\tgot LDAP_RES_INTERMEDIATE\n" );
#endif /* LDAP_SYNC_TRACE */

       assert( ls != NULL );
       assert( res != NULL );
       assert( refreshDone != NULL );

       *refreshDone = 0;

       rc = ldap_parse_intermediate( ls->ls_ld, res,
              &retoid, &retdata, NULL, 0 );
#ifdef LDAP_SYNC_TRACE
       fprintf( stderr, "\t%sldap_parse_intermediate(%s) == %d\n",
              rc != LDAP_SUCCESS ? "!!! " : "",
              retoid == NULL ? "\"\"" : retoid,
              rc );
#endif /* LDAP_SYNC_TRACE */
       /* parsing must be successful, and yield the OID
        * of the sync info intermediate response */
       if ( rc != LDAP_SUCCESS ) {
              goto done;
       }

       rc = LDAP_OTHER;

       if ( retoid == NULL || strcmp( retoid, LDAP_SYNC_INFO ) != 0 ) {
              goto done;
       }

       /* init ber using the value in the response */
       ber = ber_init( retdata );
       if ( ber == NULL ) {
              goto done;
       }

       syncinfo_tag = ber_peek_tag( ber, &len );
       switch ( syncinfo_tag ) {
       case LDAP_TAG_SYNC_NEW_COOKIE:
              if ( ber_scanf( ber, "m", &cookie ) == LBER_ERROR ) {
                     goto done;
              }
              if ( cookie.bv_val != NULL ) {
                     ber_bvreplace( &ls->ls_cookie, &cookie );
              }
#ifdef LDAP_SYNC_TRACE
              fprintf( stderr, "\t\tgot cookie=%s\n",
                     cookie.bv_val ? cookie.bv_val : "(null)" );
#endif /* LDAP_SYNC_TRACE */
              break;

       case LDAP_TAG_SYNC_REFRESH_DELETE:
       case LDAP_TAG_SYNC_REFRESH_PRESENT:
              if ( syncinfo_tag == LDAP_TAG_SYNC_REFRESH_DELETE ) {
#ifdef LDAP_SYNC_TRACE
                     fprintf( stderr, "\t\tgot refreshDelete\n" );
#endif /* LDAP_SYNC_TRACE */
                     switch ( ls->ls_refreshPhase ) {
                     case LDAP_SYNC_CAPI_NONE:
                     case LDAP_SYNC_CAPI_PRESENTS:
                            ls->ls_refreshPhase = LDAP_SYNC_CAPI_DELETES;
                            break;

                     default:
                            /* TODO: impossible; handle */
                            goto done;
                     }

              } else {
#ifdef LDAP_SYNC_TRACE
                     fprintf( stderr, "\t\tgot refreshPresent\n" );
#endif /* LDAP_SYNC_TRACE */
                     switch ( ls->ls_refreshPhase ) {
                     case LDAP_SYNC_CAPI_NONE:
                            ls->ls_refreshPhase = LDAP_SYNC_CAPI_PRESENTS;
                            break;

                     default:
                            /* TODO: impossible; handle */
                            goto done;
                     }
              }

              if ( ber_scanf( ber, "{" /*"}"*/ ) == LBER_ERROR ) {
                     goto done;
              }
              if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) {
                     if ( ber_scanf( ber, "m", &cookie ) == LBER_ERROR ) {
                            goto done;
                     }
                     if ( cookie.bv_val != NULL ) {
                            ber_bvreplace( &ls->ls_cookie, &cookie );
                     }
#ifdef LDAP_SYNC_TRACE
                     fprintf( stderr, "\t\tgot cookie=%s\n",
                            cookie.bv_val ? cookie.bv_val : "(null)" );
#endif /* LDAP_SYNC_TRACE */
              }

              *refreshDone = 1;
              if ( ber_peek_tag( ber, &len ) == LDAP_TAG_REFRESHDONE ) {
                     if ( ber_scanf( ber, "b", refreshDone ) == LBER_ERROR ) {
                            goto done;
                     }
              }

#ifdef LDAP_SYNC_TRACE
              fprintf( stderr, "\t\tgot refreshDone=%s\n",
                     *refreshDone ? "TRUE" : "FALSE" );
#endif /* LDAP_SYNC_TRACE */

              if ( ber_scanf( ber, /*"{"*/ "}" ) == LBER_ERROR ) {
                     goto done;
              }

              if ( *refreshDone ) {
                     ls->ls_refreshPhase = LDAP_SYNC_CAPI_DONE;
              }

              if ( ls->ls_intermediate ) {
                     ls->ls_intermediate( ls, res, NULL, ls->ls_refreshPhase );
              }

              break;

       case LDAP_TAG_SYNC_ID_SET:
#ifdef LDAP_SYNC_TRACE
              fprintf( stderr, "\t\tgot syncIdSet\n" );
#endif /* LDAP_SYNC_TRACE */
              if ( ber_scanf( ber, "{" /*"}"*/ ) == LBER_ERROR ) {
                     goto done;
              }
              if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) {
                     if ( ber_scanf( ber, "m", &cookie ) == LBER_ERROR ) {
                            goto done;
                     }
                     if ( cookie.bv_val != NULL ) {
                            ber_bvreplace( &ls->ls_cookie, &cookie );
                     }
#ifdef LDAP_SYNC_TRACE
                     fprintf( stderr, "\t\tgot cookie=%s\n",
                            cookie.bv_val ? cookie.bv_val : "(null)" );
#endif /* LDAP_SYNC_TRACE */
              }

              if ( ber_peek_tag( ber, &len ) == LDAP_TAG_REFRESHDELETES ) {
                     if ( ber_scanf( ber, "b", &refreshDeletes ) == LBER_ERROR ) {
                            goto done;
                     }
              }

              if ( ber_scanf( ber, /*"{"*/ "[W]}", &syncUUIDs ) == LBER_ERROR
                     || syncUUIDs == NULL )
              {
                     goto done;
              }

#ifdef LDAP_SYNC_TRACE
              {
                     int    i;

                     fprintf( stderr, "\t\tgot refreshDeletes=%s\n",
                            refreshDeletes ? "TRUE" : "FALSE" );
                     for ( i = 0; syncUUIDs[ i ].bv_val != NULL; i++ ) {
                            char   buf[ BUFSIZ ];
                            fprintf( stderr, "\t\t%s\n", 
                                   lutil_uuidstr_from_normalized(
                                          syncUUIDs[ i ].bv_val, syncUUIDs[ i ].bv_len,
                                          buf, sizeof( buf ) ) );
                     }
              }
#endif /* LDAP_SYNC_TRACE */

              if ( refreshDeletes ) {
                     phase = LDAP_SYNC_CAPI_DELETES_IDSET;

              } else {
                     phase = LDAP_SYNC_CAPI_PRESENTS_IDSET;
              }

              /* FIXME: should touch ls->ls_refreshPhase? */
              if ( ls->ls_intermediate ) {
                     ls->ls_intermediate( ls, res, syncUUIDs, phase );
              }

              ber_bvarray_free( syncUUIDs );
              break;

       default:
#ifdef LDAP_SYNC_TRACE
              fprintf( stderr, "\t\tunknown tag!\n" );
#endif /* LDAP_SYNC_TRACE */
              goto done;
       }

       rc = LDAP_SUCCESS;

done:;
       if ( ber != NULL ) {
              ber_free( ber, 1 );
       }

       if ( retoid != NULL ) {
              ldap_memfree( retoid );
       }

       if ( retdata != NULL ) {
              ber_bvfree( retdata );
       }

       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ldap_sync_search_reference ( ldap_sync_t ls,
LDAPMessage *  res 
) [static]

Definition at line 247 of file ldap_sync.c.

{
       int           rc = 0;

#ifdef LDAP_SYNC_TRACE
       fprintf( stderr, "\tgot LDAP_RES_SEARCH_REFERENCE\n" );
#endif /* LDAP_SYNC_TRACE */

       assert( ls != NULL );
       assert( res != NULL );

       if ( ls->ls_search_reference ) {
              rc = ls->ls_search_reference( ls, res );
       }

       return rc;
}

Here is the caller graph for this function:

static int ldap_sync_search_result ( ldap_sync_t ls,
LDAPMessage *  res 
) [static]

Definition at line 269 of file ldap_sync.c.

{
       int           err;
       char          *matched = NULL,
                     *msg = NULL;
       LDAPControl   **ctrls = NULL;
       int           rc;
       int           refreshDeletes = -1;

#ifdef LDAP_SYNC_TRACE
       fprintf( stderr, "\tgot LDAP_RES_SEARCH_RESULT\n" );
#endif /* LDAP_SYNC_TRACE */

       assert( ls != NULL );
       assert( res != NULL );

       /* should not happen in refreshAndPersist... */
       rc = ldap_parse_result( ls->ls_ld,
              res, &err, &matched, &msg, NULL, &ctrls, 0 );
#ifdef LDAP_SYNC_TRACE
       fprintf( stderr,
              "\tldap_parse_result(%d, \"%s\", \"%s\") == %d\n",
              err,
              matched ? matched : "",
              msg ? msg : "",
              rc );
#endif /* LDAP_SYNC_TRACE */
       if ( rc == LDAP_SUCCESS ) {
              rc = err;
       }

       ls->ls_refreshPhase = LDAP_SYNC_CAPI_DONE;

       switch ( rc ) {
       case LDAP_SUCCESS: {
              int           i;
              BerElement    *ber = NULL;
              ber_len_t     len;
              struct berval cookie = { 0 };

              rc = LDAP_OTHER;

              /* deal with control; then fallthru to handler */
              if ( ctrls == NULL ) {
                     goto done;
              }

              /* lookup the sync state control */
              for ( i = 0; ctrls[ i ] != NULL; i++ ) {
                     if ( strcmp( ctrls[ i ]->ldctl_oid,
                            LDAP_CONTROL_SYNC_DONE ) == 0 )
                     {
                            break;
                     }
              }

              /* control must be present; there might be other... */
              if ( ctrls[ i ] == NULL ) {
                     goto done;
              }

              /* extract data */
              ber = ber_init( &ctrls[ i ]->ldctl_value );
              if ( ber == NULL ) {
                     goto done;
              }

              if ( ber_scanf( ber, "{" /*"}"*/) == LBER_ERROR ) {
                     goto ber_done;
              }
              if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) {
                     if ( ber_scanf( ber, "m", &cookie ) == LBER_ERROR ) {
                            goto ber_done;
                     }
                     if ( cookie.bv_val != NULL ) {
                            ber_bvreplace( &ls->ls_cookie, &cookie );
                     }
#ifdef LDAP_SYNC_TRACE
                     fprintf( stderr, "\t\tgot cookie=%s\n",
                            cookie.bv_val ? cookie.bv_val : "(null)" );
#endif /* LDAP_SYNC_TRACE */
              }

              refreshDeletes = 0;
              if ( ber_peek_tag( ber, &len ) == LDAP_TAG_REFRESHDELETES ) {
                     if ( ber_scanf( ber, "b", &refreshDeletes ) == LBER_ERROR ) {
                            goto ber_done;
                     }
                     if ( refreshDeletes ) {
                            refreshDeletes = 1;
                     }
              }

              if ( ber_scanf( ber, /*"{"*/ "}" ) != LBER_ERROR ) {
                     rc = LDAP_SUCCESS;
              }

       ber_done:;
              ber_free( ber, 1 );
              if ( rc != LDAP_SUCCESS ) {
                     break;
              }

#ifdef LDAP_SYNC_TRACE
              fprintf( stderr, "\t\tgot refreshDeletes=%s\n",
                     refreshDeletes ? "TRUE" : "FALSE" );
#endif /* LDAP_SYNC_TRACE */

              /* FIXME: what should we do with the refreshDelete? */
              switch ( refreshDeletes ) {
              case 0:
                     ls->ls_refreshPhase = LDAP_SYNC_CAPI_PRESENTS;
                     break;

              default:
                     ls->ls_refreshPhase = LDAP_SYNC_CAPI_DELETES;
                     break;
              }

              } /* fallthru */

       case LDAP_SYNC_REFRESH_REQUIRED:
              /* TODO: check for Sync Done Control */
              /* FIXME: perhaps the handler should be called
               * also in case of failure; we'll deal with this 
               * later when implementing refreshOnly */
              if ( ls->ls_search_result ) {
                     err = ls->ls_search_result( ls, res, refreshDeletes );
              }
              break;
       }

done:;
       if ( matched != NULL ) {
              ldap_memfree( matched );
       }

       if ( msg != NULL ) {
              ldap_memfree( msg );
       }

       if ( ctrls != NULL ) {
              ldap_controls_free( ctrls );
       }

       ls->ls_refreshPhase = LDAP_SYNC_CAPI_DONE;

       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function: