1 /* ldapsync.c -- LDAP Content Sync Routines */
2 /* $OpenLDAP: pkg/ldap/servers/slapd/ldapsync.c,v 1.32.2.7 2008/02/11 23:26:44 kurt Exp $ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2003-2008 The OpenLDAP Foundation.
6 * Portions Copyright 2003 IBM Corporation.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted only as authorized by the OpenLDAP
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>.
22 #include <ac/string.h>
23 #include <ac/socket.h>
27 #include "../../libraries/liblber/lber-int.h" /* get ber_strndup() */
28 #include "lutil_ldap.h"
30 struct slap_sync_cookie_s slap_sync_cookie
=
31 LDAP_STAILQ_HEAD_INITIALIZER( slap_sync_cookie
);
34 slap_compose_sync_cookie(
36 struct berval
*cookie
,
44 for (; !BER_BVISNULL( &csn
[numcsn
] ); numcsn
++);
47 if ( numcsn
== 0 || rid
== -1 ) {
48 char cookiestr
[ LDAP_LUTIL_CSNSTR_BUFSIZE
+ 20 ];
53 len
= snprintf( cookiestr
, sizeof( cookiestr
),
56 len
+= sprintf( cookiestr
+len
, ",sid=%03x", sid
);
59 ber_str2bv_x( cookiestr
, len
, 1, cookie
,
60 op
? op
->o_tmpmemctx
: NULL
);
66 for ( i
=0; i
<numcsn
; i
++)
67 len
+= csn
[i
].bv_len
+ 1;
69 len
+= STRLENOF("rid=123,csn=");
71 len
+= STRLENOF("sid=xxx,");
73 cookie
->bv_val
= slap_sl_malloc( len
, op
? op
->o_tmpmemctx
: NULL
);
75 len
= sprintf( cookie
->bv_val
, "rid=%03d,", rid
);
76 ptr
= cookie
->bv_val
+ len
;
78 ptr
+= sprintf( ptr
, "sid=%03x,", sid
);
80 ptr
= lutil_strcopy( ptr
, "csn=" );
81 for ( i
=0; i
<numcsn
; i
++) {
82 ptr
= lutil_strncopy( ptr
, csn
[i
].bv_val
, csn
[i
].bv_len
);
87 cookie
->bv_len
= ptr
- cookie
->bv_val
;
92 slap_sync_cookie_free(
93 struct sync_cookie
*cookie
,
100 if ( cookie
->sids
) {
101 ch_free( cookie
->sids
);
105 if ( cookie
->ctxcsn
) {
106 ber_bvarray_free( cookie
->ctxcsn
);
107 cookie
->ctxcsn
= NULL
;
110 if ( !BER_BVISNULL( &cookie
->octet_str
)) {
111 ch_free( cookie
->octet_str
.bv_val
);
112 BER_BVZERO( &cookie
->octet_str
);
123 slap_parse_csn_sid( struct berval
*csnp
)
126 struct berval csn
= *csnp
;
129 p
= ber_bvchr( &csn
, '#' );
133 csn
.bv_len
-= p
- csn
.bv_val
;
136 p
= ber_bvchr( &csn
, '#' );
140 csn
.bv_len
-= p
- csn
.bv_val
;
143 q
= ber_bvchr( &csn
, '#' );
149 i
= strtol( p
, &q
, 16 );
150 if ( p
== q
|| q
!= p
+ csn
.bv_len
|| i
< 0 || i
> SLAP_SYNC_SID_MAX
) {
158 slap_parse_csn_sids( BerVarray csns
, int numcsns
, void *memctx
)
162 ret
= slap_sl_malloc( numcsns
* sizeof(int), memctx
);
163 for ( i
=0; i
<numcsns
; i
++ ) {
164 ret
[i
] = slap_parse_csn_sid( &csns
[i
] );
170 slap_parse_sync_cookie(
171 struct sync_cookie
*cookie
,
179 AttributeDescription
*ad
= slap_schema
.si_ad_modifyTimestamp
;
181 if ( cookie
== NULL
)
184 if ( cookie
->octet_str
.bv_len
<= STRLENOF( "rid=" ) )
189 cookie
->ctxcsn
= NULL
;
193 end
= cookie
->octet_str
.bv_val
+ cookie
->octet_str
.bv_len
;
195 for ( next
=cookie
->octet_str
.bv_val
; next
< end
; ) {
196 if ( !strncmp( next
, "rid=", STRLENOF("rid=") )) {
197 char *rid_ptr
= next
;
198 cookie
->rid
= strtol( &rid_ptr
[ STRLENOF( "rid=" ) ], &next
, 10 );
199 if ( next
== rid_ptr
||
201 ( *next
&& *next
!= ',' ) ||
203 cookie
->rid
> SLAP_SYNC_RID_MAX
)
207 if ( *next
== ',' ) {
215 if ( !strncmp( next
, "sid=", STRLENOF("sid=") )) {
216 char *sid_ptr
= next
;
218 cookie
->sid
= strtol( &sid_ptr
[ STRLENOF( "sid=" ) ], &next
, 16 );
219 if ( next
== sid_ptr
||
221 ( *next
&& *next
!= ',' ) ||
223 cookie
->sid
> SLAP_SYNC_SID_MAX
)
227 if ( *next
== ',' ) {
232 if ( !strncmp( next
, "csn=", STRLENOF("csn=") )) {
233 slap_syntax_validate_func
*validate
;
236 next
+= STRLENOF("csn=");
237 while ( next
< end
) {
239 /* FIXME use csnValidate when it gets implemented */
240 csn_ptr
= strchr( csn_str
, '#' );
241 if ( !csn_ptr
|| csn_ptr
> end
)
243 /* ad will be NULL when called from main. we just
244 * want to parse the rid then. But we still iterate
245 * through the string to find the end.
248 stamp
.bv_val
= csn_str
;
249 stamp
.bv_len
= csn_ptr
- csn_str
;
250 validate
= ad
->ad_type
->sat_syntax
->ssyn_validate
;
251 if ( validate( ad
->ad_type
->sat_syntax
, &stamp
)
255 cval
= strchr( csn_ptr
, ';' );
257 cval
= strchr(csn_ptr
, ',' );
259 stamp
.bv_len
= cval
- csn_str
;
261 stamp
.bv_len
= end
- csn_str
;
264 ber_dupbv_x( &bv
, &stamp
, memctx
);
265 ber_bvarray_add_x( &cookie
->ctxcsn
, &bv
, memctx
);
281 if ( cookie
->numcsns
) {
282 cookie
->sids
= slap_parse_csn_sids( cookie
->ctxcsn
, cookie
->numcsns
,
289 slap_init_sync_cookie_ctxcsn(
290 struct sync_cookie
*cookie
293 char csnbuf
[ LDAP_LUTIL_CSNSTR_BUFSIZE
+ 4 ];
294 struct berval octet_str
= BER_BVNULL
;
295 struct berval ctxcsn
= BER_BVNULL
;
297 if ( cookie
== NULL
)
300 octet_str
.bv_len
= snprintf( csnbuf
, LDAP_LUTIL_CSNSTR_BUFSIZE
+ 4,
301 "csn=%4d%02d%02d%02d%02d%02dZ#%06x#%02x#%06x",
302 1900, 1, 1, 0, 0, 0, 0, 0, 0 );
303 octet_str
.bv_val
= csnbuf
;
304 ch_free( cookie
->octet_str
.bv_val
);
305 ber_dupbv( &cookie
->octet_str
, &octet_str
);
307 ctxcsn
.bv_val
= octet_str
.bv_val
+ 4;
308 ctxcsn
.bv_len
= octet_str
.bv_len
- 4;
309 cookie
->ctxcsn
= NULL
;
310 value_add_one( &cookie
->ctxcsn
, &ctxcsn
);
318 slap_dup_sync_cookie(
319 struct sync_cookie
*dst
,
320 struct sync_cookie
*src
323 struct sync_cookie
*new;
330 ber_bvarray_free( dst
->ctxcsn
);
333 ch_free( dst
->octet_str
.bv_val
);
334 BER_BVZERO( &dst
->octet_str
);
337 new = ( struct sync_cookie
* )
338 ch_calloc( 1, sizeof( struct sync_cookie
));
343 new->numcsns
= src
->numcsns
;
345 if ( src
->numcsns
) {
346 if ( ber_bvarray_dup_x( &new->ctxcsn
, src
->ctxcsn
, NULL
)) {
352 new->sids
= ch_malloc( src
->numcsns
* sizeof(int) );
353 for (i
=0; i
<src
->numcsns
; i
++)
354 new->sids
[i
] = src
->sids
[i
];
357 if ( !BER_BVISNULL( &src
->octet_str
)) {
358 ber_dupbv( &new->octet_str
, &src
->octet_str
);