1 /* $NetBSD: slapi_dn.c,v 1.3 2021/08/14 16:15:02 christos Exp $ */
2
3 /* $OpenLDAP$ */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 *
6 * Copyright 2005-2021 The OpenLDAP Foundation.
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 /* ACKNOWLEDGEMENTS:
18 * This work was initially developed by Luke Howard for inclusion
19 * in OpenLDAP Software.
20 */
21
22 #include <sys/cdefs.h>
23 __RCSID("$NetBSD: slapi_dn.c,v 1.3 2021/08/14 16:15:02 christos Exp $");
24
25 #include "portable.h"
26
27 #include <ac/string.h>
28 #include <ac/stdarg.h>
29 #include <ac/ctype.h>
30 #include <ac/unistd.h>
31 #include <ldap_pvt.h>
32
33 #include <slap.h>
34 #include <slapi.h>
35
36 #ifdef LDAP_SLAPI
37 #define FLAG_DN 0x1
38 #define FLAG_NDN 0x2
39
slapi_sdn_init(Slapi_DN * sdn)40 void slapi_sdn_init( Slapi_DN *sdn )
41 {
42 sdn->flag = 0;
43 BER_BVZERO( &sdn->dn );
44 BER_BVZERO( &sdn->ndn );
45 }
46
slapi_sdn_new(void)47 Slapi_DN *slapi_sdn_new( void )
48 {
49 Slapi_DN *sdn;
50
51 sdn = (Slapi_DN *)slapi_ch_malloc( sizeof(*sdn ));
52 slapi_sdn_init( sdn );
53
54 return sdn;
55 }
56
slapi_sdn_done(Slapi_DN * sdn)57 void slapi_sdn_done( Slapi_DN *sdn )
58 {
59 if ( sdn == NULL )
60 return;
61
62 if ( sdn->flag & FLAG_DN ) {
63 slapi_ch_free_string( &sdn->dn.bv_val );
64 }
65 if ( sdn->flag & FLAG_NDN ) {
66 slapi_ch_free_string( &sdn->ndn.bv_val );
67 }
68
69 slapi_sdn_init( sdn );
70 }
71
slapi_sdn_free(Slapi_DN ** sdn)72 void slapi_sdn_free( Slapi_DN **sdn )
73 {
74 slapi_sdn_done( *sdn );
75 slapi_ch_free( (void **)sdn );
76 }
77
slapi_sdn_get_dn(const Slapi_DN * sdn)78 const char *slapi_sdn_get_dn( const Slapi_DN *sdn )
79 {
80 if ( !BER_BVISNULL( &sdn->dn ) )
81 return sdn->dn.bv_val;
82 else
83 return sdn->ndn.bv_val;
84 }
85
slapi_sdn_get_ndn(const Slapi_DN * sdn)86 const char *slapi_sdn_get_ndn( const Slapi_DN *sdn )
87 {
88 if ( BER_BVISNULL( &sdn->ndn ) ) {
89 dnNormalize( 0, NULL, NULL,
90 (struct berval *)&sdn->dn, (struct berval *)&sdn->ndn, NULL );
91 ((Slapi_DN *)sdn)->flag |= FLAG_NDN;
92 }
93
94 return sdn->ndn.bv_val;
95 }
96
slapi_sdn_new_dn_byval(const char * dn)97 Slapi_DN *slapi_sdn_new_dn_byval( const char *dn )
98 {
99 Slapi_DN *sdn;
100
101 sdn = slapi_sdn_new();
102 return slapi_sdn_set_dn_byval( sdn, dn );
103 }
104
slapi_sdn_new_ndn_byval(const char * ndn)105 Slapi_DN *slapi_sdn_new_ndn_byval( const char *ndn )
106 {
107 Slapi_DN *sdn;
108
109 sdn = slapi_sdn_new();
110 return slapi_sdn_set_ndn_byval( sdn, ndn );
111 }
112
slapi_sdn_new_dn_byref(const char * dn)113 Slapi_DN *slapi_sdn_new_dn_byref( const char *dn )
114 {
115 Slapi_DN *sdn;
116
117 sdn = slapi_sdn_new();
118 return slapi_sdn_set_dn_byref( sdn, dn );
119 }
120
slapi_sdn_new_ndn_byref(const char * ndn)121 Slapi_DN *slapi_sdn_new_ndn_byref( const char *ndn )
122 {
123 Slapi_DN *sdn;
124
125 sdn = slapi_sdn_new();
126 return slapi_sdn_set_ndn_byref( sdn, ndn );
127 }
128
slapi_sdn_new_dn_passin(const char * dn)129 Slapi_DN *slapi_sdn_new_dn_passin( const char *dn )
130 {
131 Slapi_DN *sdn;
132
133 sdn = slapi_sdn_new();
134 return slapi_sdn_set_dn_passin( sdn, dn );
135 }
136
slapi_sdn_set_dn_byval(Slapi_DN * sdn,const char * dn)137 Slapi_DN *slapi_sdn_set_dn_byval( Slapi_DN *sdn, const char *dn )
138 {
139 if ( sdn == NULL ) {
140 return NULL;
141 }
142
143 slapi_sdn_done( sdn );
144 if ( dn != NULL ) {
145 sdn->dn.bv_val = slapi_ch_strdup( dn );
146 sdn->dn.bv_len = strlen( dn );
147 }
148 sdn->flag |= FLAG_DN;
149
150 return sdn;
151 }
152
slapi_sdn_set_dn_byref(Slapi_DN * sdn,const char * dn)153 Slapi_DN *slapi_sdn_set_dn_byref( Slapi_DN *sdn, const char *dn )
154 {
155 if ( sdn == NULL )
156 return NULL;
157
158 slapi_sdn_done( sdn );
159 if ( dn != NULL ) {
160 sdn->dn.bv_val = (char *)dn;
161 sdn->dn.bv_len = strlen( dn );
162 }
163
164 return sdn;
165 }
166
slapi_sdn_set_dn_passin(Slapi_DN * sdn,const char * dn)167 Slapi_DN *slapi_sdn_set_dn_passin( Slapi_DN *sdn, const char *dn )
168 {
169 if ( sdn == NULL )
170 return NULL;
171
172 slapi_sdn_set_dn_byref( sdn, dn );
173 sdn->flag |= FLAG_DN;
174
175 return sdn;
176 }
177
slapi_sdn_set_ndn_byval(Slapi_DN * sdn,const char * ndn)178 Slapi_DN *slapi_sdn_set_ndn_byval( Slapi_DN *sdn, const char *ndn )
179 {
180 if ( sdn == NULL ) {
181 return NULL;
182 }
183
184 slapi_sdn_done( sdn );
185 if ( ndn != NULL ) {
186 sdn->ndn.bv_val = slapi_ch_strdup( ndn );
187 sdn->ndn.bv_len = strlen( ndn );
188 }
189 sdn->flag |= FLAG_NDN;
190
191 return sdn;
192 }
193
slapi_sdn_set_ndn_byref(Slapi_DN * sdn,const char * ndn)194 Slapi_DN *slapi_sdn_set_ndn_byref( Slapi_DN *sdn, const char *ndn )
195 {
196 if ( sdn == NULL )
197 return NULL;
198
199 slapi_sdn_done( sdn );
200 if ( ndn != NULL ) {
201 sdn->ndn.bv_val = (char *)ndn;
202 sdn->ndn.bv_len = strlen( ndn );
203 }
204
205 return sdn;
206 }
207
slapi_sdn_set_ndn_passin(Slapi_DN * sdn,const char * ndn)208 Slapi_DN *slapi_sdn_set_ndn_passin( Slapi_DN *sdn, const char *ndn )
209 {
210 if ( sdn == NULL )
211 return NULL;
212
213 slapi_sdn_set_ndn_byref( sdn, ndn );
214 sdn->flag |= FLAG_NDN;
215
216 return sdn;
217 }
218
slapi_sdn_get_parent(const Slapi_DN * sdn,Slapi_DN * sdn_parent)219 void slapi_sdn_get_parent( const Slapi_DN *sdn, Slapi_DN *sdn_parent )
220 {
221 struct berval parent_dn;
222
223 if ( !(sdn->flag & FLAG_DN) ) {
224 dnParent( (struct berval *)&sdn->ndn, &parent_dn );
225 slapi_sdn_set_ndn_byval( sdn_parent, parent_dn.bv_val );
226 } else {
227 dnParent( (struct berval *)&sdn->dn, &parent_dn );
228 slapi_sdn_set_dn_byval( sdn_parent, parent_dn.bv_val );
229 }
230 }
231
slapi_sdn_get_backend_parent(const Slapi_DN * sdn,Slapi_DN * sdn_parent,const Slapi_Backend * backend)232 void slapi_sdn_get_backend_parent( const Slapi_DN *sdn,
233 Slapi_DN *sdn_parent,
234 const Slapi_Backend *backend )
235 {
236 slapi_sdn_get_ndn( sdn );
237
238 if ( backend == NULL ||
239 be_issuffix( (Slapi_Backend *)backend, (struct berval *)&sdn->ndn ) == 0 ) {
240 slapi_sdn_get_parent( sdn, sdn_parent );
241 }
242
243 }
244
slapi_sdn_dup(const Slapi_DN * sdn)245 Slapi_DN * slapi_sdn_dup( const Slapi_DN *sdn )
246 {
247 Slapi_DN *new_sdn;
248
249 new_sdn = slapi_sdn_new();
250 slapi_sdn_copy( sdn, new_sdn );
251
252 return new_sdn;
253 }
254
slapi_sdn_copy(const Slapi_DN * from,Slapi_DN * to)255 void slapi_sdn_copy( const Slapi_DN *from, Slapi_DN *to )
256 {
257 slapi_sdn_set_dn_byval( to, from->dn.bv_val );
258 }
259
slapi_sdn_compare(const Slapi_DN * sdn1,const Slapi_DN * sdn2)260 int slapi_sdn_compare( const Slapi_DN *sdn1, const Slapi_DN *sdn2 )
261 {
262 int match = -1;
263
264 slapi_sdn_get_ndn( sdn1 );
265 slapi_sdn_get_ndn( sdn2 );
266
267 dnMatch( &match, 0, slap_schema.si_syn_distinguishedName, NULL,
268 (struct berval *)&sdn1->ndn, (void *)&sdn2->ndn );
269
270 return match;
271 }
272
slapi_sdn_isempty(const Slapi_DN * sdn)273 int slapi_sdn_isempty( const Slapi_DN *sdn)
274 {
275 return ( BER_BVISEMPTY( &sdn->dn ) && BER_BVISEMPTY( &sdn->ndn ) );
276 }
277
slapi_sdn_issuffix(const Slapi_DN * sdn,const Slapi_DN * suffix_sdn)278 int slapi_sdn_issuffix( const Slapi_DN *sdn, const Slapi_DN *suffix_sdn )
279 {
280 slapi_sdn_get_ndn( sdn );
281 slapi_sdn_get_ndn( suffix_sdn );
282
283 return dnIsSuffix( &sdn->ndn, &suffix_sdn->ndn );
284 }
285
slapi_sdn_isparent(const Slapi_DN * parent,const Slapi_DN * child)286 int slapi_sdn_isparent( const Slapi_DN *parent, const Slapi_DN *child )
287 {
288 Slapi_DN child_parent;
289
290 slapi_sdn_get_ndn( child );
291
292 slapi_sdn_init( &child_parent );
293 dnParent( (struct berval *)&child->ndn, &child_parent.ndn );
294
295 return ( slapi_sdn_compare( parent, &child_parent ) == 0 );
296 }
297
slapi_sdn_isgrandparent(const Slapi_DN * parent,const Slapi_DN * child)298 int slapi_sdn_isgrandparent( const Slapi_DN *parent, const Slapi_DN *child )
299 {
300 Slapi_DN child_grandparent;
301
302 slapi_sdn_get_ndn( child );
303
304 slapi_sdn_init( &child_grandparent );
305 dnParent( (struct berval *)&child->ndn, &child_grandparent.ndn );
306 if ( child_grandparent.ndn.bv_len == 0 ) {
307 return 0;
308 }
309
310 dnParent( &child_grandparent.ndn, &child_grandparent.ndn );
311
312 return ( slapi_sdn_compare( parent, &child_grandparent ) == 0 );
313 }
314
slapi_sdn_get_ndn_len(const Slapi_DN * sdn)315 int slapi_sdn_get_ndn_len( const Slapi_DN *sdn )
316 {
317 slapi_sdn_get_ndn( sdn );
318
319 return sdn->ndn.bv_len;
320 }
321
slapi_sdn_scope_test(const Slapi_DN * dn,const Slapi_DN * base,int scope)322 int slapi_sdn_scope_test( const Slapi_DN *dn, const Slapi_DN *base, int scope )
323 {
324 int rc;
325
326 switch ( scope ) {
327 case LDAP_SCOPE_BASE:
328 rc = ( slapi_sdn_compare( dn, base ) == 0 );
329 break;
330 case LDAP_SCOPE_ONELEVEL:
331 rc = slapi_sdn_isparent( base, dn );
332 break;
333 case LDAP_SCOPE_SUBTREE:
334 rc = slapi_sdn_issuffix( dn, base );
335 break;
336 default:
337 rc = 0;
338 break;
339 }
340
341 return rc;
342 }
343
slapi_rdn_init(Slapi_RDN * rdn)344 void slapi_rdn_init( Slapi_RDN *rdn )
345 {
346 rdn->flag = 0;
347 BER_BVZERO( &rdn->bv );
348 rdn->rdn = NULL;
349 }
350
slapi_rdn_new(void)351 Slapi_RDN *slapi_rdn_new( void )
352 {
353 Slapi_RDN *rdn;
354
355 rdn = (Slapi_RDN *)slapi_ch_malloc( sizeof(*rdn ));
356 slapi_rdn_init( rdn );
357
358 return rdn;
359 }
360
slapi_rdn_new_dn(const char * dn)361 Slapi_RDN *slapi_rdn_new_dn( const char *dn )
362 {
363 Slapi_RDN *rdn;
364
365 rdn = slapi_rdn_new();
366 slapi_rdn_init_dn( rdn, dn );
367 return rdn;
368 }
369
slapi_rdn_new_sdn(const Slapi_DN * sdn)370 Slapi_RDN *slapi_rdn_new_sdn( const Slapi_DN *sdn )
371 {
372 return slapi_rdn_new_dn( slapi_sdn_get_dn( sdn ) );
373 }
374
slapi_rdn_new_rdn(const Slapi_RDN * fromrdn)375 Slapi_RDN *slapi_rdn_new_rdn( const Slapi_RDN *fromrdn )
376 {
377 return slapi_rdn_new_dn( fromrdn->bv.bv_val );
378 }
379
slapi_rdn_init_dn(Slapi_RDN * rdn,const char * dn)380 void slapi_rdn_init_dn( Slapi_RDN *rdn, const char *dn )
381 {
382 slapi_rdn_init( rdn );
383 slapi_rdn_set_dn( rdn, dn );
384 }
385
slapi_rdn_init_sdn(Slapi_RDN * rdn,const Slapi_DN * sdn)386 void slapi_rdn_init_sdn( Slapi_RDN *rdn, const Slapi_DN *sdn )
387 {
388 slapi_rdn_init( rdn );
389 slapi_rdn_set_sdn( rdn, sdn );
390 }
391
slapi_rdn_init_rdn(Slapi_RDN * rdn,const Slapi_RDN * fromrdn)392 void slapi_rdn_init_rdn( Slapi_RDN *rdn, const Slapi_RDN *fromrdn )
393 {
394 slapi_rdn_init( rdn );
395 slapi_rdn_set_rdn( rdn, fromrdn );
396 }
397
slapi_rdn_set_dn(Slapi_RDN * rdn,const char * dn)398 void slapi_rdn_set_dn( Slapi_RDN *rdn, const char *dn )
399 {
400 struct berval bv;
401
402 slapi_rdn_done( rdn );
403
404 BER_BVZERO( &bv );
405
406 if ( dn != NULL ) {
407 bv.bv_val = (char *)dn;
408 bv.bv_len = strlen( dn );
409 }
410
411 dnExtractRdn( &bv, &rdn->bv, NULL );
412 rdn->flag |= FLAG_DN;
413 }
414
slapi_rdn_set_sdn(Slapi_RDN * rdn,const Slapi_DN * sdn)415 void slapi_rdn_set_sdn( Slapi_RDN *rdn, const Slapi_DN *sdn )
416 {
417 slapi_rdn_set_dn( rdn, slapi_sdn_get_dn( sdn ) );
418 }
419
slapi_rdn_set_rdn(Slapi_RDN * rdn,const Slapi_RDN * fromrdn)420 void slapi_rdn_set_rdn( Slapi_RDN *rdn, const Slapi_RDN *fromrdn )
421 {
422 slapi_rdn_set_dn( rdn, fromrdn->bv.bv_val );
423 }
424
slapi_rdn_free(Slapi_RDN ** rdn)425 void slapi_rdn_free( Slapi_RDN **rdn )
426 {
427 slapi_rdn_done( *rdn );
428 slapi_ch_free( (void **)rdn );
429 }
430
slapi_rdn_done(Slapi_RDN * rdn)431 void slapi_rdn_done( Slapi_RDN *rdn )
432 {
433 if ( rdn->rdn != NULL ) {
434 ldap_rdnfree( rdn->rdn );
435 rdn->rdn = NULL;
436 }
437 slapi_ch_free_string( &rdn->bv.bv_val );
438 slapi_rdn_init( rdn );
439 }
440
slapi_rdn_get_rdn(const Slapi_RDN * rdn)441 const char *slapi_rdn_get_rdn( const Slapi_RDN *rdn )
442 {
443 return rdn->bv.bv_val;
444 }
445
slapi_int_rdn_explode(Slapi_RDN * rdn)446 static int slapi_int_rdn_explode( Slapi_RDN *rdn )
447 {
448 char *next;
449
450 if ( rdn->rdn != NULL ) {
451 return LDAP_SUCCESS;
452 }
453
454 return ldap_bv2rdn( &rdn->bv, &rdn->rdn, &next, LDAP_DN_FORMAT_LDAP );
455 }
456
slapi_int_rdn_implode(Slapi_RDN * rdn)457 static int slapi_int_rdn_implode( Slapi_RDN *rdn )
458 {
459 struct berval bv;
460 int rc;
461
462 if ( rdn->rdn == NULL ) {
463 return LDAP_SUCCESS;
464 }
465
466 rc = ldap_rdn2bv( rdn->rdn, &bv, LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY );
467 if ( rc != LDAP_SUCCESS ) {
468 return rc;
469 }
470
471 slapi_ch_free_string( &rdn->bv.bv_val );
472 rdn->bv = bv;
473
474 return 0;
475 }
476
slapi_rdn_get_num_components(Slapi_RDN * rdn)477 int slapi_rdn_get_num_components( Slapi_RDN *rdn )
478 {
479 int i;
480
481 if ( slapi_int_rdn_explode( rdn ) != LDAP_SUCCESS )
482 return 0;
483
484 for ( i = 0; rdn->rdn[i] != NULL; i++ )
485 ;
486
487 return i;
488 }
489
slapi_rdn_get_first(Slapi_RDN * rdn,char ** type,char ** value)490 int slapi_rdn_get_first( Slapi_RDN *rdn, char **type, char **value )
491 {
492 return slapi_rdn_get_next( rdn, 0, type, value );
493 }
494
slapi_rdn_get_next(Slapi_RDN * rdn,int index,char ** type,char ** value)495 int slapi_rdn_get_next( Slapi_RDN *rdn, int index, char **type, char **value )
496 {
497 slapi_int_rdn_explode( rdn );
498
499 if ( rdn->rdn == NULL || rdn->rdn[index] == NULL )
500 return -1;
501
502 *type = rdn->rdn[index]->la_attr.bv_val;
503 *value = rdn->rdn[index]->la_value.bv_val;
504
505 return index + 1;
506 }
507
slapi_rdn_get_index(Slapi_RDN * rdn,const char * type,const char * value,size_t length)508 int slapi_rdn_get_index( Slapi_RDN *rdn, const char *type, const char *value, size_t length )
509 {
510 int i, match;
511 struct berval bv;
512 AttributeDescription *ad = NULL;
513 const char *text;
514
515 slapi_int_rdn_explode( rdn );
516
517 if ( slap_str2ad( type, &ad, &text ) != LDAP_SUCCESS ) {
518 return -1;
519 }
520
521 bv.bv_val = (char *)value;
522 bv.bv_len = length;
523
524 for ( i = 0; rdn->rdn[i] != NULL; i++ ) {
525 if ( !slapi_attr_types_equivalent( ad->ad_cname.bv_val, type ))
526 continue;
527
528 if ( value_match( &match, ad, ad->ad_type->sat_equality, 0,
529 &rdn->rdn[i]->la_value, (void *)&bv, &text ) != LDAP_SUCCESS )
530 match = -1;
531
532 if ( match == 0 )
533 return i;
534 }
535
536 return -1;
537 }
538
slapi_rdn_get_index_attr(Slapi_RDN * rdn,const char * type,char ** value)539 int slapi_rdn_get_index_attr( Slapi_RDN *rdn, const char *type, char **value )
540 {
541 int i;
542
543 for ( i = 0; rdn->rdn[i] != NULL; i++ ) {
544 if ( slapi_attr_types_equivalent( rdn->rdn[i]->la_attr.bv_val, type ) ) {
545 *value = rdn->rdn[i]->la_value.bv_val;
546 return i;
547 }
548 }
549
550 return -1;
551 }
552
slapi_rdn_contains(Slapi_RDN * rdn,const char * type,const char * value,size_t length)553 int slapi_rdn_contains( Slapi_RDN *rdn, const char *type, const char *value, size_t length )
554 {
555 return ( slapi_rdn_get_index( rdn, type, value, length ) != -1 );
556 }
557
slapi_rdn_contains_attr(Slapi_RDN * rdn,const char * type,char ** value)558 int slapi_rdn_contains_attr( Slapi_RDN *rdn, const char *type, char **value )
559 {
560 return ( slapi_rdn_get_index_attr( rdn, type, value ) != -1 );
561 }
562
slapi_rdn_compare(Slapi_RDN * rdn1,Slapi_RDN * rdn2)563 int slapi_rdn_compare( Slapi_RDN *rdn1, Slapi_RDN *rdn2 )
564 {
565 struct berval nrdn1 = BER_BVNULL;
566 struct berval nrdn2 = BER_BVNULL;
567 int match;
568
569 rdnNormalize( 0, NULL, NULL, (struct berval *)&rdn1->bv, &nrdn1, NULL );
570 rdnNormalize( 0, NULL, NULL, (struct berval *)&rdn2->bv, &nrdn2, NULL );
571
572 if ( rdnMatch( &match, 0, NULL, NULL, &nrdn1, (void *)&nrdn2 ) != LDAP_SUCCESS) {
573 match = -1;
574 }
575
576 return match;
577 }
578
slapi_rdn_isempty(const Slapi_RDN * rdn)579 int slapi_rdn_isempty( const Slapi_RDN *rdn )
580 {
581 return ( BER_BVISEMPTY( &rdn->bv ) );
582 }
583
slapi_rdn_add(Slapi_RDN * rdn,const char * type,const char * value)584 int slapi_rdn_add( Slapi_RDN *rdn, const char *type, const char *value )
585 {
586 char *s;
587 size_t len;
588
589 len = strlen(type) + 1 + strlen( value );
590 if ( !BER_BVISEMPTY( &rdn->bv ) ) {
591 len += 1 + rdn->bv.bv_len;
592 }
593
594 s = slapi_ch_malloc( len + 1 );
595
596 if ( BER_BVISEMPTY( &rdn->bv ) ) {
597 snprintf( s, len + 1, "%s=%s", type, value );
598 } else {
599 snprintf( s, len + 1, "%s=%s+%s", type, value, rdn->bv.bv_val );
600 }
601
602 slapi_rdn_done( rdn );
603
604 rdn->bv.bv_len = len;
605 rdn->bv.bv_val = s;
606
607 return 1;
608 }
609
slapi_rdn_remove_index(Slapi_RDN * rdn,int atindex)610 int slapi_rdn_remove_index( Slapi_RDN *rdn, int atindex )
611 {
612 int count, i;
613
614 count = slapi_rdn_get_num_components( rdn );
615
616 if ( atindex < 0 || atindex >= count )
617 return 0;
618
619 if ( rdn->rdn == NULL )
620 return 0;
621
622 slapi_ch_free_string( &rdn->rdn[atindex]->la_attr.bv_val );
623 slapi_ch_free_string( &rdn->rdn[atindex]->la_value.bv_val );
624
625 for ( i = atindex; i < count; i++ ) {
626 rdn->rdn[i] = rdn->rdn[i + 1];
627 }
628
629 if ( slapi_int_rdn_implode( rdn ) != LDAP_SUCCESS )
630 return 0;
631
632 return 1;
633 }
634
slapi_rdn_remove(Slapi_RDN * rdn,const char * type,const char * value,size_t length)635 int slapi_rdn_remove( Slapi_RDN *rdn, const char *type, const char *value, size_t length )
636 {
637 int index = slapi_rdn_get_index( rdn, type, value, length );
638
639 return slapi_rdn_remove_index( rdn, index );
640 }
641
slapi_rdn_remove_attr(Slapi_RDN * rdn,const char * type)642 int slapi_rdn_remove_attr( Slapi_RDN *rdn, const char *type )
643 {
644 char *value;
645 int index = slapi_rdn_get_index_attr( rdn, type, &value );
646
647 return slapi_rdn_remove_index( rdn, index );
648 }
649
slapi_sdn_add_rdn(Slapi_DN * sdn,const Slapi_RDN * rdn)650 Slapi_DN *slapi_sdn_add_rdn( Slapi_DN *sdn, const Slapi_RDN *rdn )
651 {
652 struct berval bv;
653
654 build_new_dn( &bv, &sdn->dn, (struct berval *)&rdn->bv, NULL );
655
656 slapi_sdn_done( sdn );
657 sdn->dn = bv;
658
659 return sdn;
660 }
661
slapi_sdn_set_parent(Slapi_DN * sdn,const Slapi_DN * parentdn)662 Slapi_DN *slapi_sdn_set_parent( Slapi_DN *sdn, const Slapi_DN *parentdn )
663 {
664 Slapi_RDN rdn;
665
666 slapi_rdn_init_sdn( &rdn, sdn );
667 slapi_sdn_set_dn_byref( sdn, slapi_sdn_get_dn( parentdn ) );
668 slapi_sdn_add_rdn( sdn, &rdn );
669 slapi_rdn_done( &rdn );
670
671 return sdn;
672 }
673
674 #endif /* LDAP_SLAPI */
675