]> git.sur5r.net Git - openldap/blob - servers/slapd/ldapsync.c
Add SLAP_MR_ORDERED_INDEX - support for inequality indexing. Currently
[openldap] / servers / slapd / ldapsync.c
1 /* ldapsync.c -- LDAP Content Sync Routines */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2003-2004 The OpenLDAP Foundation.
6  * Portions Copyright 2003 IBM Corporation.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in the file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17
18 #include "portable.h"
19
20 #include <stdio.h>
21
22 #include <ac/string.h>
23 #include <ac/socket.h>
24
25 #include "lutil.h"
26 #include "slap.h"
27 #include "../../libraries/liblber/lber-int.h" /* get ber_strndup() */
28 #include "lutil_ldap.h"
29
30 #if 0
31 struct sync_cookie *slap_sync_cookie = NULL;
32 #else
33 struct slap_sync_cookie_s slap_sync_cookie =
34         LDAP_STAILQ_HEAD_INITIALIZER( slap_sync_cookie );
35 #endif
36
37 int
38 slap_build_sync_state_ctrl(
39         Operation       *op,
40         SlapReply       *rs,
41         Entry           *e,
42         int                     entry_sync_state,
43         LDAPControl     **ctrls,
44         int                     num_ctrls,
45         int                     send_cookie,
46         struct berval   *cookie)
47 {
48         Attribute* a;
49         int ret;
50         int res;
51         const char *text = NULL;
52
53         BerElementBuffer berbuf;
54         BerElement *ber = (BerElement *)&berbuf;
55
56         struct berval entryuuid_bv      = BER_BVNULL;
57
58         ber_init2( ber, 0, LBER_USE_DER );
59         ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
60
61         ctrls[num_ctrls] = slap_sl_malloc ( sizeof ( LDAPControl ), op->o_tmpmemctx );
62
63         for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
64                 AttributeDescription *desc = a->a_desc;
65                 if ( desc == slap_schema.si_ad_entryUUID ) {
66                         ber_dupbv( &entryuuid_bv, &a->a_nvals[0] );
67                 }
68         }
69
70         if ( send_cookie && cookie ) {
71                 ber_printf( ber, "{eOON}",
72                         entry_sync_state, &entryuuid_bv, cookie );
73         } else {
74                 ber_printf( ber, "{eON}",
75                         entry_sync_state, &entryuuid_bv );
76         }
77
78         ch_free( entryuuid_bv.bv_val );
79         entryuuid_bv.bv_val = NULL;
80
81         ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_SYNC_STATE;
82         ctrls[num_ctrls]->ldctl_iscritical = op->o_sync;
83         ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
84
85         ber_free_buf( ber );
86
87         if ( ret < 0 ) {
88                 Debug( LDAP_DEBUG_TRACE,
89                         "slap_build_sync_ctrl: ber_flatten2 failed\n",
90                         0, 0, 0 );
91                 send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
92                 return ret;
93         }
94
95         return LDAP_SUCCESS;
96 }
97
98 int
99 slap_build_sync_done_ctrl(
100         Operation       *op,
101         SlapReply       *rs,
102         LDAPControl     **ctrls,
103         int                     num_ctrls,
104         int                     send_cookie,
105         struct berval *cookie,
106         int                     refreshDeletes )
107 {
108         int ret;
109         BerElementBuffer berbuf;
110         BerElement *ber = (BerElement *)&berbuf;
111
112         ber_init2( ber, NULL, LBER_USE_DER );
113         ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
114
115         ctrls[num_ctrls] = ch_malloc ( sizeof ( LDAPControl ) );
116
117         ber_printf( ber, "{" );
118         if ( send_cookie && cookie ) {
119                 ber_printf( ber, "O", cookie );
120         }
121         if ( refreshDeletes == LDAP_SYNC_REFRESH_DELETES ) {
122                 ber_printf( ber, "b", refreshDeletes );
123         }
124         ber_printf( ber, "N}" );        
125
126         ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_SYNC_DONE;
127         ctrls[num_ctrls]->ldctl_iscritical = op->o_sync;
128         ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
129
130         ber_free_buf( ber );
131
132         if ( ret < 0 ) {
133                 Debug( LDAP_DEBUG_TRACE,
134                         "slap_build_sync_done_ctrl: ber_flatten2 failed\n",
135                         0, 0, 0 );
136                 send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
137                 return ret;
138         }
139
140         return LDAP_SUCCESS;
141 }
142
143
144 int
145 slap_build_sync_state_ctrl_from_slog(
146         Operation       *op,
147         SlapReply       *rs,
148         struct slog_entry *slog_e,
149         int                     entry_sync_state,
150         LDAPControl     **ctrls,
151         int                     num_ctrls,
152         int                     send_cookie,
153         struct berval   *cookie)
154 {
155         Attribute* a;
156         int ret;
157         int res;
158         const char *text = NULL;
159
160         BerElementBuffer berbuf;
161         BerElement *ber = (BerElement *)&berbuf;
162
163         struct berval entryuuid_bv      = BER_BVNULL;
164
165         ber_init2( ber, NULL, LBER_USE_DER );
166         ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
167
168         ctrls[num_ctrls] = ch_malloc ( sizeof ( LDAPControl ) );
169
170         ber_dupbv( &entryuuid_bv, &slog_e->sl_uuid );
171
172         if ( send_cookie && cookie ) {
173                 ber_printf( ber, "{eOON}",
174                         entry_sync_state, &entryuuid_bv, cookie );
175         } else {
176                 ber_printf( ber, "{eON}",
177                         entry_sync_state, &entryuuid_bv );
178         }
179
180         ch_free( entryuuid_bv.bv_val );
181         entryuuid_bv.bv_val = NULL;
182
183         ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_SYNC_STATE;
184         ctrls[num_ctrls]->ldctl_iscritical = op->o_sync;
185         ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
186
187         ber_free_buf( ber );
188
189         if ( ret < 0 ) {
190                 Debug( LDAP_DEBUG_TRACE,
191                         "slap_build_sync_ctrl: ber_flatten2 failed\n",
192                         0, 0, 0 );
193                 send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
194                 return ret;
195         }
196
197         return LDAP_SUCCESS;
198 }
199
200 int
201 slap_send_syncinfo(
202         Operation       *op,
203         SlapReply       *rs,
204         int                     type,
205         struct berval *cookie,
206         int                     refreshDone,
207         BerVarray       syncUUIDs,
208         int                     refreshDeletes )
209 {
210         BerElementBuffer berbuf;
211         BerElement *ber = (BerElement *)&berbuf;
212         struct berval rspdata;
213
214         int ret;
215
216         ber_init2( ber, NULL, LBER_USE_DER );
217         ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
218
219         if ( type ) {
220                 switch ( type ) {
221                 case LDAP_TAG_SYNC_NEW_COOKIE:
222                         ber_printf( ber, "tO", type, cookie );
223                         break;
224                 case LDAP_TAG_SYNC_REFRESH_DELETE:
225                 case LDAP_TAG_SYNC_REFRESH_PRESENT:
226                         ber_printf( ber, "t{", type );
227                         if ( cookie ) {
228                                 ber_printf( ber, "O", cookie );
229                         }
230                         if ( refreshDone == 0 ) {
231                                 ber_printf( ber, "b", refreshDone );
232                         }
233                         ber_printf( ber, "N}" );
234                         break;
235                 case LDAP_TAG_SYNC_ID_SET:
236                         ber_printf( ber, "t{", type );
237                         if ( cookie ) {
238                                 ber_printf( ber, "O", cookie );
239                         }
240                         if ( refreshDeletes == 1 ) {
241                                 ber_printf( ber, "b", refreshDeletes );
242                         }
243                         ber_printf( ber, "[W]", syncUUIDs );
244                         ber_printf( ber, "N}" );
245                         break;
246                 default:
247                         Debug( LDAP_DEBUG_TRACE,
248                                 "slap_send_syncinfo: invalid syncinfo type (%d)\n",
249                                 type, 0, 0 );
250                         return LDAP_OTHER;
251                 }
252         }
253
254         ret = ber_flatten2( ber, &rspdata, 0 );
255
256         if ( ret < 0 ) {
257                 Debug( LDAP_DEBUG_TRACE,
258                         "slap_send_syncinfo: ber_flatten2 failed\n",
259                         0, 0, 0 );
260                 send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
261                 return ret;
262         }
263
264         rs->sr_rspdata = &rspdata;
265         send_ldap_intermediate( op, rs );
266         rs->sr_rspdata = NULL;
267         ber_free_buf( ber );
268
269         return LDAP_SUCCESS;
270 }
271
272 void
273 slap_compose_sync_cookie(
274         Operation *op,
275         struct berval *cookie,
276         struct berval *csn,
277         int sid,
278         int rid )
279 {
280         char cookiestr[ LDAP_LUTIL_CSNSTR_BUFSIZE + 20 ];
281
282         if ( csn->bv_val == NULL ) {
283                 if ( sid == -1 ) {
284                         if ( rid == -1 ) {
285                                 cookiestr[0] = '\0';
286                         } else {
287                                 snprintf( cookiestr, LDAP_LUTIL_CSNSTR_BUFSIZE + 20,
288                                                 "rid=%03d", rid );
289                         }
290                 } else {
291                         if ( rid == -1 ) {
292                                 snprintf( cookiestr, LDAP_LUTIL_CSNSTR_BUFSIZE + 20,
293                                                 "sid=%03d", sid );
294                         } else {
295                                 snprintf( cookiestr, LDAP_LUTIL_CSNSTR_BUFSIZE + 20,
296                                                 "sid=%03d,rid=%03d", sid, rid );
297                         }
298                 }
299         } else {
300                 if ( sid == -1 ) {
301                         if ( rid == -1 ) {
302                                 snprintf( cookiestr, LDAP_LUTIL_CSNSTR_BUFSIZE + 20,
303                                                 "csn=%s", csn->bv_val );
304                         } else {
305                                 snprintf( cookiestr, LDAP_LUTIL_CSNSTR_BUFSIZE + 20,
306                                                 "csn=%s,rid=%03d", csn->bv_val, rid );
307                         }
308                 } else {
309                         if ( rid == -1 ) {
310                                 snprintf( cookiestr, LDAP_LUTIL_CSNSTR_BUFSIZE + 20,
311                                                 "csn=%s,sid=%03d", csn->bv_val, sid );
312                         } else {
313                                 snprintf( cookiestr, LDAP_LUTIL_CSNSTR_BUFSIZE + 20,
314                                                 "csn=%s,sid=%03d,rid=%03d", csn->bv_val, sid, rid );
315                         }
316                 }
317         }
318         ber_str2bv( cookiestr, strlen(cookiestr), 1, cookie );
319 }
320
321 void
322 slap_sync_cookie_free(
323         struct sync_cookie *cookie,
324         int free_cookie
325 )
326 {
327         if ( cookie == NULL )
328                 return;
329
330         if ( cookie->ctxcsn ) {
331                 ber_bvarray_free( cookie->ctxcsn );
332                 cookie->ctxcsn = NULL;
333         }
334
335         if ( cookie->octet_str ) {
336                 ber_bvarray_free( cookie->octet_str );
337                 cookie->octet_str = NULL;
338         }
339
340         if ( free_cookie ) {
341                 ch_free( cookie );
342         }
343
344         return;
345 }
346
347 int
348 slap_parse_sync_cookie(
349         struct sync_cookie *cookie
350 )
351 {
352         char *csn_ptr;
353         char *csn_str;
354         int csn_str_len;
355         char *sid_ptr;
356         char *sid_str;
357         char *rid_ptr;
358         char *rid_str;
359         char *cval;
360         struct berval *ctxcsn;
361
362         if ( cookie == NULL )
363                 return -1;
364
365         if (( csn_ptr = strstr( cookie->octet_str[0].bv_val, "csn=" )) != NULL ) {
366                 csn_str = SLAP_STRNDUP( csn_ptr, LDAP_LUTIL_CSNSTR_BUFSIZE );
367                 if ( (cval = strchr( csn_str, ',' )) != NULL ) {
368                         *cval = '\0';
369                         csn_str_len = cval - csn_str - (sizeof("csn=") - 1);
370                 } else {
371                         csn_str_len = cookie->octet_str[0].bv_len -
372                                                         (csn_ptr - cookie->octet_str[0].bv_val) -
373                                                         (sizeof("csn=") - 1);
374                 }
375                 ctxcsn = ber_str2bv( csn_str + (sizeof("csn=")-1),
376                                                          csn_str_len, 1, NULL );
377                 ch_free( csn_str );
378                 ber_bvarray_add( &cookie->ctxcsn, ctxcsn );
379                 ch_free( ctxcsn );
380         } else {
381                 cookie->ctxcsn = NULL;
382         }
383
384         if (( sid_ptr = strstr( cookie->octet_str->bv_val, "sid=" )) != NULL ) {
385                 sid_str = SLAP_STRNDUP( sid_ptr,
386                                                         SLAP_SYNC_SID_SIZE + sizeof("sid=") - 1 );
387                 if ( (cval = strchr( sid_str, ',' )) != NULL ) {
388                         *cval = '\0';
389                 }
390                 cookie->sid = atoi( sid_str + sizeof("sid=") - 1 );
391                 ch_free( sid_str );
392         } else {
393                 cookie->sid = -1;
394         }
395
396         if (( rid_ptr = strstr( cookie->octet_str->bv_val, "rid=" )) != NULL ) {
397                 rid_str = SLAP_STRNDUP( rid_ptr,
398                                                         SLAP_SYNC_RID_SIZE + sizeof("rid=") - 1 );
399                 if ( (cval = strchr( rid_str, ',' )) != NULL ) {
400                         *cval = '\0';
401                 }
402                 cookie->rid = atoi( rid_str + sizeof("rid=") - 1 );
403                 ch_free( rid_str );
404         } else {
405                 cookie->rid = -1;
406         }
407         return 0;
408 }
409
410 int
411 slap_init_sync_cookie_ctxcsn(
412         struct sync_cookie *cookie
413 )
414 {
415         char csnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE + 4 ];
416         struct berval octet_str = BER_BVNULL;
417         struct berval ctxcsn = BER_BVNULL;
418         struct berval ctxcsn_dup = BER_BVNULL;
419         struct berval slap_syncCookie;
420
421         if ( cookie == NULL )
422                 return -1;
423
424         octet_str.bv_len = snprintf( csnbuf, LDAP_LUTIL_CSNSTR_BUFSIZE + 4,
425                                         "csn=%4d%02d%02d%02d%02d%02dZ#%06x#%02x#%06x",
426                                         1900, 1, 1, 0, 0, 0, 0, 0, 0 );
427         octet_str.bv_val = csnbuf;
428         build_new_dn( &slap_syncCookie, &cookie->octet_str[0], &octet_str, NULL );
429         ber_bvarray_free( cookie->octet_str );
430         cookie->octet_str = NULL;
431         ber_bvarray_add( &cookie->octet_str, &slap_syncCookie );
432
433         ber_dupbv( &ctxcsn, &octet_str );
434         ctxcsn.bv_val += 4;
435         ctxcsn.bv_len -= 4;
436         ber_dupbv( &ctxcsn_dup, &ctxcsn );
437         ch_free( ctxcsn.bv_val );
438         ber_bvarray_add( &cookie->ctxcsn, &ctxcsn_dup );
439
440         return 0;
441 }
442
443 struct sync_cookie *
444 slap_dup_sync_cookie(
445         struct sync_cookie *dst,
446         struct sync_cookie *src
447 )
448 {
449         int i;
450         struct sync_cookie *new;
451         struct berval tmp_bv;
452
453         if ( src == NULL )
454                 return NULL;
455
456         if ( dst ) {
457                 ber_bvarray_free( dst->ctxcsn );
458                 ber_bvarray_free( dst->octet_str );
459                 new = dst;
460         } else {
461                 new = ( struct sync_cookie * )
462                                 ch_calloc( 1, sizeof( struct sync_cookie ));
463         }
464
465         new->sid = src->sid;
466         new->rid = src->rid;
467
468         if ( src->ctxcsn ) {
469                 for ( i=0; src->ctxcsn[i].bv_val; i++ ) {
470                         ber_dupbv( &tmp_bv, &src->ctxcsn[i] );
471                         ber_bvarray_add( &new->ctxcsn, &tmp_bv );
472                 }
473         }
474
475         if ( src->octet_str ) {
476                 for ( i=0; src->octet_str[i].bv_val; i++ ) {
477                         ber_dupbv( &tmp_bv, &src->octet_str[i] );
478                         ber_bvarray_add( &new->octet_str, &tmp_bv );
479                 }
480         }
481
482         return new;
483 }
484
485 int
486 slap_build_syncUUID_set(
487         Operation *op,
488         BerVarray *set,
489         Entry *e
490 )
491 {
492         int ret;
493         Attribute* a;
494
495         struct berval entryuuid_bv      = BER_BVNULL;
496
497         for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
498                 AttributeDescription *desc = a->a_desc;
499                 if ( desc == slap_schema.si_ad_entryUUID ) {
500                         ber_dupbv_x( &entryuuid_bv, &a->a_nvals[0], op->o_tmpmemctx );
501                 }
502         }
503
504         ret = ber_bvarray_add_x( set, &entryuuid_bv, op->o_tmpmemctx );
505
506         return ret;
507 }