No empty .Rs/.Re
[netbsd-mini2440.git] / external / bsd / openldap / dist / libraries / libldap / ldap_sync.c
blob5d24aebecab0a0d07357c9cce89fd5944d67675f
1 /* $OpenLDAP: pkg/ldap/libraries/libldap/ldap_sync.c,v 1.2.2.3 2008/02/11 23:26:41 kurt Exp $ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 2006-2008 The OpenLDAP Foundation.
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted only as authorized by the OpenLDAP
9 * Public License.
11 * A copy of this license is available in the file LICENSE in the
12 * top-level directory of the distribution or, alternatively, at
13 * <http://www.OpenLDAP.org/license.html>.
15 /* ACKNOWLEDGEMENTS:
16 * This program was originally developed by Pierangelo Masarati
17 * for inclusion in OpenLDAP Software.
21 * Proof-of-concept API that implement the client-side
22 * of the "LDAP Content Sync Operation" (RFC 4533)
25 #include "portable.h"
27 #include <ac/time.h>
29 #include "ldap-int.h"
31 #ifdef LDAP_SYNC_TRACE
32 static const char *
33 ldap_sync_state2str( int state )
35 switch ( state ) {
36 case LDAP_SYNC_PRESENT:
37 return "LDAP_SYNC_PRESENT";
39 case LDAP_SYNC_ADD:
40 return "LDAP_SYNC_ADD";
42 case LDAP_SYNC_MODIFY:
43 return "LDAP_SYNC_MODIFY";
45 case LDAP_SYNC_DELETE:
46 return "LDAP_SYNC_DELETE";
48 default:
49 return "(unknown)";
52 #endif
55 * initialize the persistent search structure
57 ldap_sync_t *
58 ldap_sync_initialize( ldap_sync_t *ls_in )
60 ldap_sync_t *ls = ls_in;
62 if ( ls == NULL ) {
63 ls = ldap_memalloc( sizeof( ldap_sync_t ) );
64 if ( ls == NULL ) {
65 return NULL;
68 } else {
69 memset( ls, 0, sizeof( ldap_sync_t ) );
72 ls->ls_scope = LDAP_SCOPE_SUBTREE;
73 ls->ls_timeout = -1;
75 return ls;
79 * destroy the persistent search structure
81 void
82 ldap_sync_destroy( ldap_sync_t *ls, int freeit )
84 assert( ls != NULL );
86 if ( ls->ls_base != NULL ) {
87 ldap_memfree( ls->ls_base );
88 ls->ls_base = NULL;
91 if ( ls->ls_filter != NULL ) {
92 ldap_memfree( ls->ls_filter );
93 ls->ls_filter = NULL;
96 if ( ls->ls_attrs != NULL ) {
97 int i;
99 for ( i = 0; ls->ls_attrs[ i ] != NULL; i++ ) {
100 ldap_memfree( ls->ls_attrs[ i ] );
102 ldap_memfree( ls->ls_attrs );
103 ls->ls_attrs = NULL;
106 if ( ls->ls_ld != NULL ) {
107 (void)ldap_unbind_ext( ls->ls_ld, NULL, NULL );
108 #ifdef LDAP_SYNC_TRACE
109 fprintf( stderr, "ldap_unbind_ext()\n" );
110 #endif /* LDAP_SYNC_TRACE */
111 ls->ls_ld = NULL;
114 if ( ls->ls_cookie.bv_val != NULL ) {
115 ldap_memfree( ls->ls_cookie.bv_val );
116 ls->ls_cookie.bv_val = NULL;
119 if ( freeit ) {
120 ldap_memfree( ls );
125 * handle the LDAP_RES_SEARCH_ENTRY response
127 static int
128 ldap_sync_search_entry( ldap_sync_t *ls, LDAPMessage *res )
130 LDAPControl **ctrls = NULL;
131 int rc = LDAP_SUCCESS,
133 BerElement *ber = NULL;
134 struct berval entryUUID = { 0 },
135 cookie = { 0 };
136 int state = -1;
137 ber_len_t len;
138 ldap_sync_refresh_t phase = ls->ls_refreshPhase;
140 #ifdef LDAP_SYNC_TRACE
141 fprintf( stderr, "\tgot LDAP_RES_SEARCH_ENTRY\n" );
142 #endif /* LDAP_SYNC_TRACE */
144 assert( ls != NULL );
145 assert( res != NULL );
147 /* OK */
149 /* extract:
150 * - data
151 * - entryUUID
153 * check that:
154 * - Sync State Control is "add"
157 /* the control MUST be present */
159 /* extract controls */
160 ldap_get_entry_controls( ls->ls_ld, res, &ctrls );
161 if ( ctrls == NULL ) {
162 rc = LDAP_OTHER;
163 goto done;
166 /* lookup the sync state control */
167 for ( i = 0; ctrls[ i ] != NULL; i++ ) {
168 if ( strcmp( ctrls[ i ]->ldctl_oid, LDAP_CONTROL_SYNC_STATE ) == 0 ) {
169 break;
173 /* control must be present; there might be other... */
174 if ( ctrls[ i ] == NULL ) {
175 rc = LDAP_OTHER;
176 goto done;
179 /* extract data */
180 ber = ber_init( &ctrls[ i ]->ldctl_value );
181 /* scan entryUUID in-place ("m") */
182 ber_scanf( ber, "{em" /*"}"*/, &state, &entryUUID );
183 if ( entryUUID.bv_len == 0 ) {
184 rc = LDAP_OTHER;
185 goto done;
188 if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) {
189 /* scan cookie in-place ("m") */
190 ber_scanf( ber, /*"{"*/ "m}", &cookie );
191 if ( cookie.bv_val != NULL ) {
192 ber_bvreplace( &ls->ls_cookie, &cookie );
194 #ifdef LDAP_SYNC_TRACE
195 fprintf( stderr, "\t\tgot cookie=%s\n",
196 cookie.bv_val ? cookie.bv_val : "(null)" );
197 #endif /* LDAP_SYNC_TRACE */
200 switch ( state ) {
201 case LDAP_SYNC_PRESENT:
202 case LDAP_SYNC_DELETE:
203 case LDAP_SYNC_ADD:
204 case LDAP_SYNC_MODIFY:
205 /* NOTE: ldap_sync_refresh_t is defined
206 * as the corresponding LDAP_SYNC_*
207 * for the 4 above cases */
208 phase = state;
209 #ifdef LDAP_SYNC_TRACE
210 fprintf( stderr, "\t\tgot syncState=%s\n", ldap_sync_state2str( state ) );
211 #endif /* LDAP_SYNC_TRACE */
212 break;
214 default:
215 rc = LDAP_OTHER;
216 #ifdef LDAP_SYNC_TRACE
217 fprintf( stderr, "\t\tgot unknown syncState=%d\n", state );
218 #endif /* LDAP_SYNC_TRACE */
219 goto done;
222 if ( ls->ls_search_entry ) {
223 rc = ls->ls_search_entry( ls, res, &entryUUID, phase );
226 done:;
227 if ( ber != NULL ) {
228 ber_free( ber, 1 );
231 if ( ctrls != NULL ) {
232 ldap_controls_free( ctrls );
235 return rc;
239 * handle the LDAP_RES_SEARCH_REFERENCE response
240 * (to be implemented yet)
242 static int
243 ldap_sync_search_reference( ldap_sync_t *ls, LDAPMessage *res )
245 int rc = 0;
247 #ifdef LDAP_SYNC_TRACE
248 fprintf( stderr, "\tgot LDAP_RES_SEARCH_REFERENCE\n" );
249 #endif /* LDAP_SYNC_TRACE */
251 assert( ls != NULL );
252 assert( res != NULL );
254 if ( ls->ls_search_reference ) {
255 rc = ls->ls_search_reference( ls, res );
258 return rc;
262 * handle the LDAP_RES_SEARCH_RESULT response
264 static int
265 ldap_sync_search_result( ldap_sync_t *ls, LDAPMessage *res )
267 int err;
268 char *matched = NULL,
269 *msg = NULL;
270 LDAPControl **ctrls = NULL;
271 int rc;
272 int refreshDeletes = -1;
274 #ifdef LDAP_SYNC_TRACE
275 fprintf( stderr, "\tgot LDAP_RES_SEARCH_RESULT\n" );
276 #endif /* LDAP_SYNC_TRACE */
278 assert( ls != NULL );
279 assert( res != NULL );
281 /* should not happen in refreshAndPersist... */
282 rc = ldap_parse_result( ls->ls_ld,
283 res, &err, &matched, &msg, NULL, &ctrls, 0 );
284 #ifdef LDAP_SYNC_TRACE
285 fprintf( stderr,
286 "\tldap_parse_result(%d, \"%s\", \"%s\") == %d\n",
287 err,
288 matched ? matched : "",
289 msg ? msg : "",
290 rc );
291 #endif /* LDAP_SYNC_TRACE */
292 if ( rc == LDAP_SUCCESS ) {
293 rc = err;
296 ls->ls_refreshPhase = LDAP_SYNC_CAPI_DONE;
298 switch ( rc ) {
299 case LDAP_SUCCESS: {
300 int i;
301 BerElement *ber = NULL;
302 ber_len_t len;
303 struct berval cookie = { 0 };
305 /* deal with control; then fallthru to handler */
306 if ( ctrls == NULL ) {
307 rc = LDAP_OTHER;
308 goto done;
311 /* lookup the sync state control */
312 for ( i = 0; ctrls[ i ] != NULL; i++ ) {
313 if ( strcmp( ctrls[ i ]->ldctl_oid,
314 LDAP_CONTROL_SYNC_DONE ) == 0 )
316 break;
320 /* control must be present; there might be other... */
321 if ( ctrls[ i ] == NULL ) {
322 rc = LDAP_OTHER;
323 goto done;
326 /* extract data */
327 ber = ber_init( &ctrls[ i ]->ldctl_value );
329 ber_scanf( ber, "{" /*"}"*/);
330 if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) {
331 ber_scanf( ber, "m", &cookie );
332 if ( cookie.bv_val != NULL ) {
333 ber_bvreplace( &ls->ls_cookie, &cookie );
335 #ifdef LDAP_SYNC_TRACE
336 fprintf( stderr, "\t\tgot cookie=%s\n",
337 cookie.bv_val ? cookie.bv_val : "(null)" );
338 #endif /* LDAP_SYNC_TRACE */
341 refreshDeletes = 0;
342 if ( ber_peek_tag( ber, &len ) == LDAP_TAG_REFRESHDELETES ) {
343 ber_scanf( ber, "b", &refreshDeletes );
344 if ( refreshDeletes ) {
345 refreshDeletes = 1;
349 ber_scanf( ber, /*"{"*/ "}" );
351 /* NOTE: if any goto/return between ber_init() and here
352 * is introduced, don't forget to ber_free() */
353 ber_free( ber, 1 );
355 #ifdef LDAP_SYNC_TRACE
356 fprintf( stderr, "\t\tgot refreshDeletes=%s\n",
357 refreshDeletes ? "TRUE" : "FALSE" );
358 #endif /* LDAP_SYNC_TRACE */
360 /* FIXME: what should we do with the refreshDelete? */
361 switch ( refreshDeletes ) {
362 case 0:
363 ls->ls_refreshPhase = LDAP_SYNC_CAPI_PRESENTS;
364 break;
366 default:
367 ls->ls_refreshPhase = LDAP_SYNC_CAPI_DELETES;
368 break;
371 } /* fallthru */
373 case LDAP_SYNC_REFRESH_REQUIRED:
374 /* TODO: check for Sync Done Control */
375 /* FIXME: perhaps the handler should be called
376 * also in case of failure; we'll deal with this
377 * later when implementing refreshOnly */
378 if ( ls->ls_search_result ) {
379 err = ls->ls_search_result( ls, res, refreshDeletes );
381 break;
383 default:
384 break;
387 done:;
388 if ( matched != NULL ) {
389 ldap_memfree( matched );
392 if ( msg != NULL ) {
393 ldap_memfree( msg );
396 if ( ctrls != NULL ) {
397 ldap_controls_free( ctrls );
400 ls->ls_refreshPhase = LDAP_SYNC_CAPI_DONE;
402 return rc;
406 * handle the LDAP_RES_INTERMEDIATE response
408 static int
409 ldap_sync_search_intermediate( ldap_sync_t *ls, LDAPMessage *res, int *refreshDone )
411 int rc;
412 char *retoid = NULL;
413 struct berval *retdata = NULL;
414 BerElement *ber = NULL;
415 ber_len_t len;
416 ber_tag_t tag,
417 syncinfo_tag;
418 struct berval cookie;
419 int refreshDeletes = 0;
420 BerVarray syncUUIDs = NULL;
421 ldap_sync_refresh_t phase;
423 #ifdef LDAP_SYNC_TRACE
424 fprintf( stderr, "\tgot LDAP_RES_INTERMEDIATE\n" );
425 #endif /* LDAP_SYNC_TRACE */
427 assert( ls != NULL );
428 assert( res != NULL );
429 assert( refreshDone != NULL );
431 *refreshDone = 0;
433 rc = ldap_parse_intermediate( ls->ls_ld, res,
434 &retoid, &retdata, NULL, 0 );
435 #ifdef LDAP_SYNC_TRACE
436 fprintf( stderr, "\t%sldap_parse_intermediate(%s) == %d\n",
437 rc != LDAP_SUCCESS ? "!!! " : "",
438 retoid == NULL ? "\"\"" : retoid,
439 rc );
440 #endif /* LDAP_SYNC_TRACE */
441 /* parsing must be successful, and yield the OID
442 * of the sync info intermediate response */
443 if ( rc != LDAP_SUCCESS ) {
444 goto done;
447 if ( retoid == NULL || strcmp( retoid, LDAP_SYNC_INFO ) != 0 ) {
448 rc = LDAP_OTHER;
449 goto done;
452 /* init ber using the value in the response */
453 ber = ber_init( retdata );
454 if ( ber == NULL ) {
455 goto done;
458 syncinfo_tag = ber_peek_tag( ber, &len );
459 switch ( syncinfo_tag ) {
460 case LDAP_TAG_SYNC_NEW_COOKIE:
461 ber_scanf( ber, "tm", &tag, &cookie );
462 if ( cookie.bv_val != NULL ) {
463 ber_bvreplace( &ls->ls_cookie, &cookie );
465 #ifdef LDAP_SYNC_TRACE
466 fprintf( stderr, "\t\tgot cookie=%s\n",
467 cookie.bv_val ? cookie.bv_val : "(null)" );
468 #endif /* LDAP_SYNC_TRACE */
469 break;
471 case LDAP_TAG_SYNC_REFRESH_DELETE:
472 case LDAP_TAG_SYNC_REFRESH_PRESENT:
473 if ( syncinfo_tag == LDAP_TAG_SYNC_REFRESH_DELETE ) {
474 #ifdef LDAP_SYNC_TRACE
475 fprintf( stderr, "\t\tgot refreshDelete\n" );
476 #endif /* LDAP_SYNC_TRACE */
477 switch ( ls->ls_refreshPhase ) {
478 case LDAP_SYNC_CAPI_NONE:
479 case LDAP_SYNC_CAPI_PRESENTS:
480 ls->ls_refreshPhase = LDAP_SYNC_CAPI_DELETES;
481 break;
483 default:
484 /* TODO: impossible; handle */
485 rc = LDAP_OTHER;
486 goto done;
489 } else {
490 #ifdef LDAP_SYNC_TRACE
491 fprintf( stderr, "\t\tgot refreshPresent\n" );
492 #endif /* LDAP_SYNC_TRACE */
493 switch ( ls->ls_refreshPhase ) {
494 case LDAP_SYNC_CAPI_NONE:
495 ls->ls_refreshPhase = LDAP_SYNC_CAPI_PRESENTS;
496 break;
498 default:
499 /* TODO: impossible; handle */
500 rc = LDAP_OTHER;
501 goto done;
505 ber_scanf( ber, "t{" /*"}"*/, &tag );
506 if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) {
507 ber_scanf( ber, "m", &cookie );
508 if ( cookie.bv_val != NULL ) {
509 ber_bvreplace( &ls->ls_cookie, &cookie );
511 #ifdef LDAP_SYNC_TRACE
512 fprintf( stderr, "\t\tgot cookie=%s\n",
513 cookie.bv_val ? cookie.bv_val : "(null)" );
514 #endif /* LDAP_SYNC_TRACE */
517 *refreshDone = 1;
518 if ( ber_peek_tag( ber, &len ) == LDAP_TAG_REFRESHDONE ) {
519 ber_scanf( ber, "b", refreshDone );
522 #ifdef LDAP_SYNC_TRACE
523 fprintf( stderr, "\t\tgot refreshDone=%s\n",
524 *refreshDone ? "TRUE" : "FALSE" );
525 #endif /* LDAP_SYNC_TRACE */
527 ber_scanf( ber, /*"{"*/ "}" );
529 if ( *refreshDone ) {
530 ls->ls_refreshPhase = LDAP_SYNC_CAPI_DONE;
533 if ( ls->ls_intermediate ) {
534 ls->ls_intermediate( ls, res, NULL, ls->ls_refreshPhase );
537 break;
539 case LDAP_TAG_SYNC_ID_SET:
540 #ifdef LDAP_SYNC_TRACE
541 fprintf( stderr, "\t\tgot syncIdSet\n" );
542 #endif /* LDAP_SYNC_TRACE */
543 ber_scanf( ber, "t{" /*"}"*/, &tag );
544 if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) {
545 ber_scanf( ber, "m", &cookie );
546 if ( cookie.bv_val != NULL ) {
547 ber_bvreplace( &ls->ls_cookie, &cookie );
549 #ifdef LDAP_SYNC_TRACE
550 fprintf( stderr, "\t\tgot cookie=%s\n",
551 cookie.bv_val ? cookie.bv_val : "(null)" );
552 #endif /* LDAP_SYNC_TRACE */
555 if ( ber_peek_tag( ber, &len ) == LDAP_TAG_REFRESHDELETES ) {
556 ber_scanf( ber, "b", &refreshDeletes );
559 ber_scanf( ber, "[W]", &syncUUIDs );
560 ber_scanf( ber, /*"{"*/ "}" );
561 if ( syncUUIDs == NULL ) {
562 rc = LDAP_OTHER;
563 goto done;
566 #ifdef LDAP_SYNC_TRACE
568 int i;
570 fprintf( stderr, "\t\tgot refreshDeletes=%s\n",
571 refreshDeletes ? "TRUE" : "FALSE" );
572 for ( i = 0; syncUUIDs[ i ].bv_val != NULL; i++ ) {
573 char buf[ BUFSIZ ];
574 fprintf( stderr, "\t\t%s\n",
575 lutil_uuidstr_from_normalized(
576 syncUUIDs[ i ].bv_val, syncUUIDs[ i ].bv_len,
577 buf, sizeof( buf ) ) );
580 #endif /* LDAP_SYNC_TRACE */
582 if ( refreshDeletes ) {
583 phase = LDAP_SYNC_CAPI_DELETES_IDSET;
585 } else {
586 phase = LDAP_SYNC_CAPI_PRESENTS_IDSET;
589 /* FIXME: should touch ls->ls_refreshPhase? */
590 if ( ls->ls_intermediate ) {
591 ls->ls_intermediate( ls, res, syncUUIDs, phase );
594 ber_bvarray_free( syncUUIDs );
595 break;
597 default:
598 #ifdef LDAP_SYNC_TRACE
599 fprintf( stderr, "\t\tunknown tag!\n" );
600 #endif /* LDAP_SYNC_TRACE */
601 goto done;
604 done:;
605 if ( ber != NULL ) {
606 ber_free( ber, 1 );
609 if ( retoid != NULL ) {
610 ldap_memfree( retoid );
613 if ( retdata != NULL ) {
614 ber_bvfree( retdata );
617 return rc;
621 * initialize the sync
624 ldap_sync_init( ldap_sync_t *ls, int mode )
626 LDAPControl ctrl = { 0 },
627 *ctrls[ 2 ];
628 BerElement *ber = NULL;
629 int rc;
630 struct timeval tv = { 0 },
631 *tvp = NULL;
632 LDAPMessage *res = NULL;
634 #ifdef LDAP_SYNC_TRACE
635 fprintf( stderr, "ldap_sync_init(%s)...\n",
636 mode == LDAP_SYNC_REFRESH_AND_PERSIST ?
637 "LDAP_SYNC_REFRESH_AND_PERSIST" :
638 ( mode == LDAP_SYNC_REFRESH_ONLY ?
639 "LDAP_SYNC_REFRESH_ONLY" : "unknown" ) );
640 #endif /* LDAP_SYNC_TRACE */
642 assert( ls != NULL );
643 assert( ls->ls_ld != NULL );
645 /* support both refreshOnly and refreshAndPersist */
646 switch ( mode ) {
647 case LDAP_SYNC_REFRESH_AND_PERSIST:
648 case LDAP_SYNC_REFRESH_ONLY:
649 break;
651 default:
652 fprintf( stderr, "ldap_sync_init: unknown mode=%d\n", mode );
653 return LDAP_PARAM_ERROR;
656 /* check consistency of cookie and reloadHint at initial refresh */
657 if ( ls->ls_cookie.bv_val == NULL && ls->ls_reloadHint != 0 ) {
658 fprintf( stderr, "ldap_sync_init: inconsistent cookie/rhint\n" );
659 return LDAP_PARAM_ERROR;
662 ctrls[ 0 ] = &ctrl;
663 ctrls[ 1 ] = NULL;
665 /* prepare the Sync Request control */
666 ber = ber_alloc_t( LBER_USE_DER );
667 #ifdef LDAP_SYNC_TRACE
668 fprintf( stderr, "%sber_alloc_t() %s= NULL\n",
669 ber == NULL ? "!!! " : "",
670 ber == NULL ? "=" : "!" );
671 #endif /* LDAP_SYNC_TRACE */
672 if ( ber == NULL ) {
673 rc = LDAP_NO_MEMORY;
674 goto done;
677 ls->ls_refreshPhase = LDAP_SYNC_CAPI_NONE;
679 if ( ls->ls_cookie.bv_val != NULL ) {
680 ber_printf( ber, "{eOb}", mode,
681 &ls->ls_cookie, ls->ls_reloadHint );
683 } else {
684 ber_printf( ber, "{eb}", mode, ls->ls_reloadHint );
687 rc = ber_flatten2( ber, &ctrl.ldctl_value, 0 );
688 #ifdef LDAP_SYNC_TRACE
689 fprintf( stderr,
690 "%sber_flatten2() == %d\n",
691 rc ? "!!! " : "",
692 rc );
693 #endif /* LDAP_SYNC_TRACE */
694 if ( rc == LBER_ERROR ) {
695 rc = LDAP_OTHER;
696 goto done;
699 /* make the control critical, as we cannot proceed without */
700 ctrl.ldctl_oid = LDAP_CONTROL_SYNC;
701 ctrl.ldctl_iscritical = 1;
703 /* timelimit? */
704 if ( ls->ls_timelimit ) {
705 tv.tv_sec = ls->ls_timelimit;
706 tvp = &tv;
709 /* actually run the search */
710 rc = ldap_search_ext( ls->ls_ld,
711 ls->ls_base, ls->ls_scope, ls->ls_filter,
712 ls->ls_attrs, 0, ctrls, NULL,
713 tvp, ls->ls_sizelimit, &ls->ls_msgid );
714 #ifdef LDAP_SYNC_TRACE
715 fprintf( stderr,
716 "%sldap_search_ext(\"%s\", %d, \"%s\") == %d\n",
717 rc ? "!!! " : "",
718 ls->ls_base, ls->ls_scope, ls->ls_filter, rc );
719 #endif /* LDAP_SYNC_TRACE */
720 if ( rc != LDAP_SUCCESS ) {
721 goto done;
724 /* initial content/content update phase */
725 for ( ; ; ) {
726 LDAPMessage *msg = NULL;
728 /* NOTE: this very short timeout is just to let
729 * ldap_result() yield long enough to get something */
730 tv.tv_sec = 0;
731 tv.tv_usec = 100000;
733 rc = ldap_result( ls->ls_ld, ls->ls_msgid,
734 LDAP_MSG_RECEIVED, &tv, &res );
735 #ifdef LDAP_SYNC_TRACE
736 fprintf( stderr,
737 "\t%sldap_result(%d) == %d\n",
738 rc == -1 ? "!!! " : "",
739 ls->ls_msgid, rc );
740 #endif /* LDAP_SYNC_TRACE */
741 switch ( rc ) {
742 case 0:
744 * timeout
746 * TODO: can do something else in the meanwhile)
748 break;
750 case -1:
751 /* smtg bad! */
752 goto done;
754 default:
755 for ( msg = ldap_first_message( ls->ls_ld, res );
756 msg != NULL;
757 msg = ldap_next_message( ls->ls_ld, msg ) )
759 int refreshDone;
761 switch ( ldap_msgtype( msg ) ) {
762 case LDAP_RES_SEARCH_ENTRY:
763 rc = ldap_sync_search_entry( ls, res );
764 break;
766 case LDAP_RES_SEARCH_REFERENCE:
767 rc = ldap_sync_search_reference( ls, res );
768 break;
770 case LDAP_RES_SEARCH_RESULT:
771 rc = ldap_sync_search_result( ls, res );
772 goto done_search;
774 case LDAP_RES_INTERMEDIATE:
775 rc = ldap_sync_search_intermediate( ls, res, &refreshDone );
776 if ( rc != LDAP_SUCCESS || refreshDone ) {
777 goto done_search;
779 break;
781 default:
782 #ifdef LDAP_SYNC_TRACE
783 fprintf( stderr, "\tgot something unexpected...\n" );
784 #endif /* LDAP_SYNC_TRACE */
786 ldap_msgfree( res );
788 rc = LDAP_OTHER;
789 goto done;
792 ldap_msgfree( res );
793 res = NULL;
794 break;
798 done_search:;
799 ldap_msgfree( res );
801 done:;
802 if ( ber != NULL ) {
803 ber_free( ber, 1 );
806 return rc;
810 * initialize the refreshOnly sync
813 ldap_sync_init_refresh_only( ldap_sync_t *ls )
815 return ldap_sync_init( ls, LDAP_SYNC_REFRESH_ONLY );
819 * initialize the refreshAndPersist sync
822 ldap_sync_init_refresh_and_persist( ldap_sync_t *ls )
824 return ldap_sync_init( ls, LDAP_SYNC_REFRESH_AND_PERSIST );
828 * poll for new responses
831 ldap_sync_poll( ldap_sync_t *ls )
833 struct timeval tv,
834 *tvp = NULL;
835 LDAPMessage *res = NULL,
836 *msg;
837 int rc = 0;
839 #ifdef LDAP_SYNC_TRACE
840 fprintf( stderr, "ldap_sync_poll...\n" );
841 #endif /* LDAP_SYNC_TRACE */
843 assert( ls != NULL );
844 assert( ls->ls_ld != NULL );
846 if ( ls->ls_timeout != -1 ) {
847 tv.tv_sec = ls->ls_timeout;
848 tv.tv_usec = 0;
849 tvp = &tv;
852 rc = ldap_result( ls->ls_ld, ls->ls_msgid,
853 LDAP_MSG_RECEIVED, tvp, &res );
854 if ( rc <= 0 ) {
855 return rc;
858 for ( msg = ldap_first_message( ls->ls_ld, res );
859 msg;
860 msg = ldap_next_message( ls->ls_ld, msg ) )
862 int refreshDone;
864 switch ( ldap_msgtype( msg ) ) {
865 case LDAP_RES_SEARCH_ENTRY:
866 rc = ldap_sync_search_entry( ls, res );
867 break;
869 case LDAP_RES_SEARCH_REFERENCE:
870 rc = ldap_sync_search_reference( ls, res );
871 break;
873 case LDAP_RES_SEARCH_RESULT:
874 rc = ldap_sync_search_result( ls, res );
875 goto done_search;
877 case LDAP_RES_INTERMEDIATE:
878 rc = ldap_sync_search_intermediate( ls, res, &refreshDone );
879 if ( rc != LDAP_SUCCESS || refreshDone ) {
880 goto done_search;
882 break;
884 default:
885 #ifdef LDAP_SYNC_TRACE
886 fprintf( stderr, "\tgot something unexpected...\n" );
887 #endif /* LDAP_SYNC_TRACE */
889 ldap_msgfree( res );
891 rc = LDAP_OTHER;
892 goto done;
896 done_search:;
897 ldap_msgfree( res );
899 done:;
900 return rc;