1 /* $NetBSD: plugin.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 2002-2021 The OpenLDAP Foundation.
7 * Portions Copyright 1997,2002-2003 IBM Corporation.
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted only as authorized by the OpenLDAP
12 * Public License.
13 *
14 * A copy of this license is available in the file LICENSE in the
15 * top-level directory of the distribution or, alternatively, at
16 * <http://www.OpenLDAP.org/license.html>.
17 */
18 /* ACKNOWLEDGEMENTS:
19 * This work was initially developed by IBM Corporation for use in
20 * IBM products and subsequently ported to OpenLDAP Software by
21 * Steve Omrani. Additional significant contributors include:
22 * Luke Howard
23 */
24
25 #include <sys/cdefs.h>
26 __RCSID("$NetBSD: plugin.c,v 1.3 2021/08/14 16:15:02 christos Exp $");
27
28 #include "portable.h"
29
30 /*
31 * Note: if ltdl.h is not available, slapi should not be compiled
32 */
33
34 #ifdef HAVE_LTDL_H
35 #include "ldap_pvt_thread.h"
36 #include "slap.h"
37 #include "slap-config.h"
38 #include "slapi.h"
39 #include "lutil.h"
40
41 #include <ltdl.h>
42
43 static int slapi_int_load_plugin( Slapi_PBlock *, const char *, const char *, int,
44 SLAPI_FUNC *, lt_dlhandle * );
45
46 /* pointer to link list of extended objects */
47 static ExtendedOp *pGExtendedOps = NULL;
48
49 /*********************************************************************
50 * Function Name: plugin_pblock_new
51 *
52 * Description: This routine creates a new Slapi_PBlock structure,
53 * loads in the plugin module and executes the init
54 * function provided by the module.
55 *
56 * Input: type - type of the plugin, such as SASL, database, etc.
57 * path - the loadpath to load the module in
58 * initfunc - name of the plugin function to execute first
59 * argc - number of arguments
60 * argv[] - an array of char pointers point to
61 * the arguments passed in via
62 * the configuration file.
63 *
64 * Output:
65 *
66 * Return Values: a pointer to a newly created Slapi_PBlock structure or
67 * NULL - function failed
68 *
69 * Messages: None
70 *********************************************************************/
71
72 static Slapi_PBlock *
plugin_pblock_new(int type,int argc,char * argv[])73 plugin_pblock_new(
74 int type,
75 int argc,
76 char *argv[] )
77 {
78 Slapi_PBlock *pPlugin = NULL;
79 Slapi_PluginDesc *pPluginDesc = NULL;
80 lt_dlhandle hdLoadHandle;
81 int rc;
82 char **av2 = NULL, **ppPluginArgv;
83 char *path = argv[2];
84 char *initfunc = argv[3];
85
86 pPlugin = slapi_pblock_new();
87 if ( pPlugin == NULL ) {
88 rc = LDAP_NO_MEMORY;
89 goto done;
90 }
91
92 slapi_pblock_set( pPlugin, SLAPI_PLUGIN_TYPE, (void *)&type );
93 slapi_pblock_set( pPlugin, SLAPI_PLUGIN_ARGC, (void *)&argc );
94
95 av2 = ldap_charray_dup( argv );
96 if ( av2 == NULL ) {
97 rc = LDAP_NO_MEMORY;
98 goto done;
99 }
100
101 if ( argc > 0 ) {
102 ppPluginArgv = &av2[4];
103 } else {
104 ppPluginArgv = NULL;
105 }
106
107 slapi_pblock_set( pPlugin, SLAPI_PLUGIN_ARGV, (void *)ppPluginArgv );
108 slapi_pblock_set( pPlugin, SLAPI_X_CONFIG_ARGV, (void *)av2 );
109
110 rc = slapi_int_load_plugin( pPlugin, path, initfunc, 1, NULL, &hdLoadHandle );
111 if ( rc != 0 ) {
112 goto done;
113 }
114
115 if ( slapi_pblock_get( pPlugin, SLAPI_PLUGIN_DESCRIPTION, (void **)&pPluginDesc ) == 0 &&
116 pPluginDesc != NULL ) {
117 slapi_log_error(SLAPI_LOG_TRACE, "plugin_pblock_new",
118 "Registered plugin %s %s [%s] (%s)\n",
119 pPluginDesc->spd_id,
120 pPluginDesc->spd_version,
121 pPluginDesc->spd_vendor,
122 pPluginDesc->spd_description);
123 }
124
125 done:
126 if ( rc != 0 && pPlugin != NULL ) {
127 slapi_pblock_destroy( pPlugin );
128 pPlugin = NULL;
129 if ( av2 != NULL ) {
130 ldap_charray_free( av2 );
131 }
132 }
133
134 return pPlugin;
135 }
136
137 /*********************************************************************
138 * Function Name: slapi_int_register_plugin
139 *
140 * Description: insert the slapi_pblock structure to a given position the end of the plugin
141 * list
142 *
143 * Input: a pointer to a plugin slapi_pblock structure to be added to
144 * the list
145 *
146 * Output: none
147 *
148 * Return Values: LDAP_SUCCESS - successfully inserted.
149 * LDAP_LOCAL_ERROR.
150 *
151 * Messages: None
152 *********************************************************************/
153 int
slapi_int_register_plugin_index(Backend * be,Slapi_PBlock * pPB,int index)154 slapi_int_register_plugin_index(
155 Backend *be,
156 Slapi_PBlock *pPB,
157 int index )
158 {
159 Slapi_PBlock *pTmpPB;
160 Slapi_PBlock *pSavePB;
161 int pos = 0, rc = LDAP_SUCCESS;
162
163 assert( be != NULL );
164
165 pTmpPB = SLAPI_BACKEND_PBLOCK( be );
166 if ( pTmpPB == NULL || index == 0 ) {
167 SLAPI_BACKEND_PBLOCK( be ) = pPB;
168 } else {
169 while ( pTmpPB != NULL && rc == LDAP_SUCCESS &&
170 ( index < 0 || pos++ < index ) ) {
171 pSavePB = pTmpPB;
172 rc = slapi_pblock_get( pTmpPB, SLAPI_IBM_PBLOCK, &pTmpPB );
173 }
174
175 if ( rc == LDAP_SUCCESS ) {
176 rc = slapi_pblock_set( pSavePB, SLAPI_IBM_PBLOCK, (void *)pPB );
177 }
178 }
179
180 if ( index >= 0 && rc == LDAP_SUCCESS ) {
181 rc = slapi_pblock_set( pPB, SLAPI_IBM_PBLOCK, (void *)pTmpPB );
182 }
183
184 return ( rc != LDAP_SUCCESS ) ? LDAP_OTHER : LDAP_SUCCESS;
185 }
186
187 int
slapi_int_register_plugin(Backend * be,Slapi_PBlock * pPB)188 slapi_int_register_plugin(
189 Backend *be,
190 Slapi_PBlock *pPB )
191 {
192 return slapi_int_register_plugin_index( be, pPB, -1 );
193 }
194
195 /*********************************************************************
196 * Function Name: slapi_int_get_plugins
197 *
198 * Description: get the desired type of function pointers defined
199 * in all the plugins
200 *
201 * Input: the type of the functions to get, such as pre-operation,etc.
202 *
203 * Output: none
204 *
205 * Return Values: this routine returns a pointer to an array of function
206 * pointers containing backend-specific plugin functions
207 * followed by global plugin functions
208 *
209 * Messages: None
210 *********************************************************************/
211 int
slapi_int_get_plugins(Backend * be,int functype,SLAPI_FUNC ** ppFuncPtrs)212 slapi_int_get_plugins(
213 Backend *be,
214 int functype,
215 SLAPI_FUNC **ppFuncPtrs )
216 {
217
218 Slapi_PBlock *pCurrentPB;
219 SLAPI_FUNC FuncPtr;
220 SLAPI_FUNC *pTmpFuncPtr;
221 int numPB = 0;
222 int rc = LDAP_SUCCESS;
223
224 assert( ppFuncPtrs != NULL );
225 *ppFuncPtrs = NULL;
226
227 if ( be == NULL ) {
228 goto done;
229 }
230
231 pCurrentPB = SLAPI_BACKEND_PBLOCK( be );
232
233 while ( pCurrentPB != NULL && rc == LDAP_SUCCESS ) {
234 rc = slapi_pblock_get( pCurrentPB, functype, &FuncPtr );
235 if ( rc == LDAP_SUCCESS ) {
236 if ( FuncPtr != NULL ) {
237 numPB++;
238 }
239 rc = slapi_pblock_get( pCurrentPB,
240 SLAPI_IBM_PBLOCK, &pCurrentPB );
241 }
242 }
243
244 if ( numPB == 0 ) {
245 rc = LDAP_SUCCESS;
246 goto done;
247 }
248
249 /*
250 * Now, build the function pointer array of backend-specific
251 * plugins followed by global plugins.
252 */
253 *ppFuncPtrs = pTmpFuncPtr =
254 (SLAPI_FUNC *)ch_malloc( ( numPB + 1 ) * sizeof(SLAPI_FUNC) );
255 if ( ppFuncPtrs == NULL ) {
256 rc = LDAP_NO_MEMORY;
257 goto done;
258 }
259
260 pCurrentPB = SLAPI_BACKEND_PBLOCK( be );
261
262 while ( pCurrentPB != NULL && rc == LDAP_SUCCESS ) {
263 rc = slapi_pblock_get( pCurrentPB, functype, &FuncPtr );
264 if ( rc == LDAP_SUCCESS ) {
265 if ( FuncPtr != NULL ) {
266 *pTmpFuncPtr = FuncPtr;
267 pTmpFuncPtr++;
268 }
269 rc = slapi_pblock_get( pCurrentPB,
270 SLAPI_IBM_PBLOCK, &pCurrentPB );
271 }
272 }
273
274 *pTmpFuncPtr = NULL;
275
276
277 done:
278 if ( rc != LDAP_SUCCESS && *ppFuncPtrs != NULL ) {
279 ch_free( *ppFuncPtrs );
280 *ppFuncPtrs = NULL;
281 }
282
283 return rc;
284 }
285
286 /*********************************************************************
287 * Function Name: createExtendedOp
288 *
289 * Description: Creates an extended operation structure and
290 * initializes the fields
291 *
292 * Return value: A newly allocated structure or NULL
293 ********************************************************************/
294 ExtendedOp *
createExtendedOp()295 createExtendedOp()
296 {
297 ExtendedOp *ret;
298
299 ret = (ExtendedOp *)slapi_ch_malloc(sizeof(ExtendedOp));
300 ret->ext_oid.bv_val = NULL;
301 ret->ext_oid.bv_len = 0;
302 ret->ext_func = NULL;
303 ret->ext_be = NULL;
304 ret->ext_next = NULL;
305
306 return ret;
307 }
308
309
310 /*********************************************************************
311 * Function Name: slapi_int_unregister_extop
312 *
313 * Description: This routine removes the ExtendedOp structures
314 * asscoiated with a particular extended operation
315 * plugin.
316 *
317 * Input: pBE - pointer to a backend structure
318 * opList - pointer to a linked list of extended
319 * operation structures
320 * pPB - pointer to a slapi parameter block
321 *
322 * Output:
323 *
324 * Return Value: none
325 *
326 * Messages: None
327 *********************************************************************/
328 void
slapi_int_unregister_extop(Backend * pBE,ExtendedOp ** opList,Slapi_PBlock * pPB)329 slapi_int_unregister_extop(
330 Backend *pBE,
331 ExtendedOp **opList,
332 Slapi_PBlock *pPB )
333 {
334 ExtendedOp *pTmpExtOp, *backExtOp;
335 char **pTmpOIDs;
336 int i;
337
338 #if 0
339 assert( pBE != NULL); /* unused */
340 #endif /* 0 */
341 assert( opList != NULL );
342 assert( pPB != NULL );
343
344 if ( *opList == NULL ) {
345 return;
346 }
347
348 slapi_pblock_get( pPB, SLAPI_PLUGIN_EXT_OP_OIDLIST, &pTmpOIDs );
349 if ( pTmpOIDs == NULL ) {
350 return;
351 }
352
353 for ( i = 0; pTmpOIDs[i] != NULL; i++ ) {
354 backExtOp = NULL;
355 pTmpExtOp = *opList;
356 for ( ; pTmpExtOp != NULL; pTmpExtOp = pTmpExtOp->ext_next) {
357 int rc;
358 rc = strcasecmp( pTmpExtOp->ext_oid.bv_val,
359 pTmpOIDs[ i ] );
360 if ( rc == 0 ) {
361 if ( backExtOp == NULL ) {
362 *opList = pTmpExtOp->ext_next;
363 } else {
364 backExtOp->ext_next
365 = pTmpExtOp->ext_next;
366 }
367
368 ch_free( pTmpExtOp );
369 break;
370 }
371 backExtOp = pTmpExtOp;
372 }
373 }
374 }
375
376
377 /*********************************************************************
378 * Function Name: slapi_int_register_extop
379 *
380 * Description: This routine creates a new ExtendedOp structure, loads
381 * in the extended op module and put the extended op function address
382 * in the structure. The function will not be executed in
383 * this routine.
384 *
385 * Input: pBE - pointer to a backend structure
386 * opList - pointer to a linked list of extended
387 * operation structures
388 * pPB - pointer to a slapi parameter block
389 *
390 * Output:
391 *
392 * Return Value: an LDAP return code
393 *
394 * Messages: None
395 *********************************************************************/
396 int
slapi_int_register_extop(Backend * pBE,ExtendedOp ** opList,Slapi_PBlock * pPB)397 slapi_int_register_extop(
398 Backend *pBE,
399 ExtendedOp **opList,
400 Slapi_PBlock *pPB )
401 {
402 ExtendedOp *pTmpExtOp = NULL;
403 SLAPI_FUNC tmpFunc;
404 char **pTmpOIDs;
405 int rc = LDAP_OTHER;
406 int i;
407
408 if ( (*opList) == NULL ) {
409 *opList = createExtendedOp();
410 if ( (*opList) == NULL ) {
411 rc = LDAP_NO_MEMORY;
412 goto error_return;
413 }
414 pTmpExtOp = *opList;
415
416 } else { /* Find the end of the list */
417 for ( pTmpExtOp = *opList; pTmpExtOp->ext_next != NULL;
418 pTmpExtOp = pTmpExtOp->ext_next )
419 ; /* EMPTY */
420 pTmpExtOp->ext_next = createExtendedOp();
421 if ( pTmpExtOp->ext_next == NULL ) {
422 rc = LDAP_NO_MEMORY;
423 goto error_return;
424 }
425 pTmpExtOp = pTmpExtOp->ext_next;
426 }
427
428 rc = slapi_pblock_get( pPB,SLAPI_PLUGIN_EXT_OP_OIDLIST, &pTmpOIDs );
429 if ( rc != 0 ) {
430 rc = LDAP_OTHER;
431 goto error_return;
432 }
433
434 rc = slapi_pblock_get(pPB,SLAPI_PLUGIN_EXT_OP_FN, &tmpFunc);
435 if ( rc != 0 ) {
436 rc = LDAP_OTHER;
437 goto error_return;
438 }
439
440 if ( (pTmpOIDs == NULL) || (tmpFunc == NULL) ) {
441 rc = LDAP_OTHER;
442 goto error_return;
443 }
444
445 for ( i = 0; pTmpOIDs[i] != NULL; i++ ) {
446 pTmpExtOp->ext_oid.bv_val = pTmpOIDs[i];
447 pTmpExtOp->ext_oid.bv_len = strlen( pTmpOIDs[i] );
448 pTmpExtOp->ext_func = tmpFunc;
449 pTmpExtOp->ext_be = pBE;
450 if ( pTmpOIDs[i + 1] != NULL ) {
451 pTmpExtOp->ext_next = createExtendedOp();
452 if ( pTmpExtOp->ext_next == NULL ) {
453 rc = LDAP_NO_MEMORY;
454 break;
455 }
456 pTmpExtOp = pTmpExtOp->ext_next;
457 }
458 }
459
460 error_return:
461 return rc;
462 }
463
464 /*********************************************************************
465 * Function Name: slapi_int_get_extop_plugin
466 *
467 * Description: This routine gets the function address for a given function
468 * name.
469 *
470 * Input:
471 * funcName - name of the extended op function, ie. an OID.
472 *
473 * Output: pFuncAddr - the function address of the requested function name.
474 *
475 * Return Values: a pointer to a newly created ExtendOp structure or
476 * NULL - function failed
477 *
478 * Messages: None
479 *********************************************************************/
480 int
slapi_int_get_extop_plugin(struct berval * reqoid,SLAPI_FUNC * pFuncAddr)481 slapi_int_get_extop_plugin(
482 struct berval *reqoid,
483 SLAPI_FUNC *pFuncAddr )
484 {
485 ExtendedOp *pTmpExtOp;
486
487 assert( reqoid != NULL );
488 assert( pFuncAddr != NULL );
489
490 *pFuncAddr = NULL;
491
492 if ( pGExtendedOps == NULL ) {
493 return LDAP_OTHER;
494 }
495
496 pTmpExtOp = pGExtendedOps;
497 while ( pTmpExtOp != NULL ) {
498 int rc;
499
500 rc = strcasecmp( reqoid->bv_val, pTmpExtOp->ext_oid.bv_val );
501 if ( rc == 0 ) {
502 *pFuncAddr = pTmpExtOp->ext_func;
503 break;
504 }
505 pTmpExtOp = pTmpExtOp->ext_next;
506 }
507
508 return ( *pFuncAddr == NULL ? 1 : 0 );
509 }
510
511 /***************************************************************************
512 * This function is similar to slapi_int_get_extop_plugin above. except it returns one OID
513 * per call. It is called from root_dse_info (root_dse.c).
514 * The function is a modified version of get_supported_extop (file extended.c).
515 ***************************************************************************/
516 struct berval *
slapi_int_get_supported_extop(int index)517 slapi_int_get_supported_extop( int index )
518 {
519 ExtendedOp *ext;
520
521 for ( ext = pGExtendedOps ; ext != NULL && --index >= 0;
522 ext = ext->ext_next) {
523 ; /* empty */
524 }
525
526 if ( ext == NULL ) {
527 return NULL;
528 }
529
530 return &ext->ext_oid ;
531 }
532
533 /*********************************************************************
534 * Function Name: slapi_int_load_plugin
535 *
536 * Description: This routine loads the specified DLL, gets and executes the init function
537 * if requested.
538 *
539 * Input:
540 * pPlugin - a pointer to a Slapi_PBlock struct which will be passed to
541 * the DLL init function.
542 * path - path name of the DLL to be load.
543 * initfunc - either the DLL initialization function or an OID of the
544 * loaded extended operation.
545 * doInit - if it is TRUE, execute the init function, otherwise, save the
546 * function address but not execute it.
547 *
548 * Output: pInitFunc - the function address of the loaded function. This param
549 * should be not be null if doInit is FALSE.
550 * pLdHandle - handle returned by lt_dlopen()
551 *
552 * Return Values: LDAP_SUCCESS, LDAP_LOCAL_ERROR
553 *
554 * Messages: None
555 *********************************************************************/
556
557 static int
slapi_int_load_plugin(Slapi_PBlock * pPlugin,const char * path,const char * initfunc,int doInit,SLAPI_FUNC * pInitFunc,lt_dlhandle * pLdHandle)558 slapi_int_load_plugin(
559 Slapi_PBlock *pPlugin,
560 const char *path,
561 const char *initfunc,
562 int doInit,
563 SLAPI_FUNC *pInitFunc,
564 lt_dlhandle *pLdHandle )
565 {
566 int rc = LDAP_SUCCESS;
567 SLAPI_FUNC fpInitFunc = NULL;
568
569 assert( pLdHandle != NULL );
570
571 if ( lt_dlinit() ) {
572 return LDAP_LOCAL_ERROR;
573 }
574
575 /* load in the module */
576 *pLdHandle = lt_dlopen( path );
577 if ( *pLdHandle == NULL ) {
578 fprintf( stderr, "failed to load plugin %s: %s\n",
579 path, lt_dlerror() );
580 return LDAP_LOCAL_ERROR;
581 }
582
583 fpInitFunc = (SLAPI_FUNC)lt_dlsym( *pLdHandle, initfunc );
584 if ( fpInitFunc == NULL ) {
585 fprintf( stderr, "failed to find symbol %s in plugin %s: %s\n",
586 initfunc, path, lt_dlerror() );
587 lt_dlclose( *pLdHandle );
588 return LDAP_LOCAL_ERROR;
589 }
590
591 if ( doInit ) {
592 rc = ( *fpInitFunc )( pPlugin );
593 if ( rc != LDAP_SUCCESS ) {
594 lt_dlclose( *pLdHandle );
595 }
596
597 } else {
598 *pInitFunc = fpInitFunc;
599 }
600
601 return rc;
602 }
603
604 /*
605 * Special support for computed attribute plugins
606 */
607 int
slapi_int_call_plugins(Backend * be,int funcType,Slapi_PBlock * pPB)608 slapi_int_call_plugins(
609 Backend *be,
610 int funcType,
611 Slapi_PBlock *pPB )
612 {
613
614 int rc = 0;
615 SLAPI_FUNC *pGetPlugin = NULL, *tmpPlugin = NULL;
616
617 if ( pPB == NULL ) {
618 return 1;
619 }
620
621 rc = slapi_int_get_plugins( be, funcType, &tmpPlugin );
622 if ( rc != LDAP_SUCCESS || tmpPlugin == NULL ) {
623 /* Nothing to do, front-end should ignore. */
624 return rc;
625 }
626
627 for ( pGetPlugin = tmpPlugin ; *pGetPlugin != NULL; pGetPlugin++ ) {
628 rc = (*pGetPlugin)(pPB);
629
630 /*
631 * Only non-postoperation plugins abort processing on
632 * failure (confirmed with SLAPI specification).
633 */
634 if ( !SLAPI_PLUGIN_IS_POST_FN( funcType ) && rc != 0 ) {
635 /*
636 * Plugins generally return negative error codes
637 * to indicate failure, although in the case of
638 * bind plugins they may return SLAPI_BIND_xxx
639 */
640 break;
641 }
642 }
643
644 slapi_ch_free( (void **)&tmpPlugin );
645
646 return rc;
647 }
648
649 int
slapi_int_read_config(Backend * be,const char * fname,int lineno,int argc,char ** argv,int index)650 slapi_int_read_config(
651 Backend *be,
652 const char *fname,
653 int lineno,
654 int argc,
655 char **argv,
656 int index )
657 {
658 int iType = -1;
659 int numPluginArgc = 0;
660
661 if ( argc < 4 ) {
662 fprintf( stderr,
663 "%s: line %d: missing arguments "
664 "in \"plugin <plugin_type> <lib_path> "
665 "<init_function> [<arguments>]\" line\n",
666 fname, lineno );
667 return 1;
668 }
669
670 /* automatically instantiate overlay if necessary */
671 if ( !slapi_over_is_inst( be ) ) {
672 ConfigReply cr = { 0 };
673 if ( slapi_over_config( be, &cr ) != 0 ) {
674 fprintf( stderr, "Failed to instantiate SLAPI overlay: "
675 "err=%d msg=\"%s\"\n", cr.err, cr.msg );
676 return -1;
677 }
678 }
679
680 if ( strcasecmp( argv[1], "preoperation" ) == 0 ) {
681 iType = SLAPI_PLUGIN_PREOPERATION;
682 } else if ( strcasecmp( argv[1], "postoperation" ) == 0 ) {
683 iType = SLAPI_PLUGIN_POSTOPERATION;
684 } else if ( strcasecmp( argv[1], "extendedop" ) == 0 ) {
685 iType = SLAPI_PLUGIN_EXTENDEDOP;
686 } else if ( strcasecmp( argv[1], "object" ) == 0 ) {
687 iType = SLAPI_PLUGIN_OBJECT;
688 } else {
689 fprintf( stderr, "%s: line %d: invalid plugin type \"%s\".\n",
690 fname, lineno, argv[1] );
691 return 1;
692 }
693
694 numPluginArgc = argc - 4;
695
696 if ( iType == SLAPI_PLUGIN_PREOPERATION ||
697 iType == SLAPI_PLUGIN_EXTENDEDOP ||
698 iType == SLAPI_PLUGIN_POSTOPERATION ||
699 iType == SLAPI_PLUGIN_OBJECT ) {
700 int rc;
701 Slapi_PBlock *pPlugin;
702
703 pPlugin = plugin_pblock_new( iType, numPluginArgc, argv );
704 if (pPlugin == NULL) {
705 return 1;
706 }
707
708 if (iType == SLAPI_PLUGIN_EXTENDEDOP) {
709 rc = slapi_int_register_extop(be, &pGExtendedOps, pPlugin);
710 if ( rc != LDAP_SUCCESS ) {
711 slapi_pblock_destroy( pPlugin );
712 return 1;
713 }
714 }
715
716 rc = slapi_int_register_plugin_index( be, pPlugin, index );
717 if ( rc != LDAP_SUCCESS ) {
718 if ( iType == SLAPI_PLUGIN_EXTENDEDOP ) {
719 slapi_int_unregister_extop( be, &pGExtendedOps, pPlugin );
720 }
721 slapi_pblock_destroy( pPlugin );
722 return 1;
723 }
724 }
725
726 return 0;
727 }
728
729 int
slapi_int_unregister_plugin(Backend * be,Slapi_PBlock * pPlugin,Slapi_PBlock * pPrev)730 slapi_int_unregister_plugin(
731 Backend *be,
732 Slapi_PBlock *pPlugin,
733 Slapi_PBlock *pPrev
734 )
735 {
736 int type;
737
738 assert( pPlugin != NULL );
739
740 slapi_pblock_get( pPlugin, SLAPI_PLUGIN_TYPE, (void *)&type );
741 if ( type == SLAPI_PLUGIN_EXTENDEDOP ) {
742 slapi_int_unregister_extop( be, &pGExtendedOps, pPlugin );
743 }
744
745 if ( pPrev != NULL ) {
746 Slapi_PBlock *pNext = NULL;
747
748 slapi_pblock_get( pPlugin, SLAPI_IBM_PBLOCK, &pNext );
749 slapi_pblock_set( pPrev, SLAPI_IBM_PBLOCK, &pNext );
750 }
751 slapi_pblock_destroy( pPlugin );
752
753 return LDAP_SUCCESS;
754 }
755
756 int
slapi_int_unregister_plugins(Backend * be,int index)757 slapi_int_unregister_plugins(
758 Backend *be,
759 int index
760 )
761 {
762 Slapi_PBlock *pTmpPB = NULL;
763 Slapi_PBlock *pSavePB = NULL;
764 int rc = LDAP_SUCCESS;
765
766 pTmpPB = SLAPI_BACKEND_PBLOCK( be );
767 if ( pTmpPB == NULL ) {
768 return ( index < 0 ) ? LDAP_SUCCESS : LDAP_OTHER;
769 }
770
771 if ( index < 0 ) {
772 /* All plugins must go */
773 while ( pTmpPB != NULL && rc == LDAP_SUCCESS ) {
774 pSavePB = pTmpPB;
775 rc = slapi_pblock_get( pTmpPB, SLAPI_IBM_PBLOCK, &pTmpPB );
776 if ( pSavePB != NULL ) {
777 slapi_int_unregister_plugin( be, pSavePB, NULL );
778 }
779 }
780 } else if ( index == 0 ) {
781 slapi_pblock_get( pTmpPB, SLAPI_IBM_PBLOCK, &pSavePB );
782 SLAPI_BACKEND_PBLOCK( be ) = pSavePB;
783 slapi_int_unregister_plugin( be, pTmpPB, NULL );
784 } else {
785 int pos = -1;
786 while ( pTmpPB != NULL && rc == LDAP_SUCCESS && ++pos < index ) {
787 pSavePB = pTmpPB;
788 rc = slapi_pblock_get( pTmpPB, SLAPI_IBM_PBLOCK, &pTmpPB );
789 }
790 if ( pos == index ) {
791 slapi_int_unregister_plugin( be, pTmpPB, pSavePB );
792 }
793 }
794 return rc;
795 }
796
797 void
slapi_int_plugin_unparse(Backend * be,BerVarray * out)798 slapi_int_plugin_unparse(
799 Backend *be,
800 BerVarray *out
801 )
802 {
803 Slapi_PBlock *pp;
804 int i, j;
805 char **argv, ibuf[32], *ptr;
806 struct berval idx, bv;
807
808 *out = NULL;
809 idx.bv_val = ibuf;
810 i = 0;
811
812 for ( pp = SLAPI_BACKEND_PBLOCK( be );
813 pp != NULL;
814 slapi_pblock_get( pp, SLAPI_IBM_PBLOCK, &pp ) )
815 {
816 slapi_pblock_get( pp, SLAPI_X_CONFIG_ARGV, &argv );
817 if ( argv == NULL ) /* could be dynamic plugin */
818 continue;
819 idx.bv_len = snprintf( idx.bv_val, sizeof( ibuf ), "{%d}", i );
820 if ( idx.bv_len >= sizeof( ibuf ) ) {
821 /* FIXME: just truncating by now */
822 idx.bv_len = sizeof( ibuf ) - 1;
823 }
824 bv.bv_len = idx.bv_len;
825 for (j=1; argv[j]; j++) {
826 bv.bv_len += strlen(argv[j]);
827 if ( j ) bv.bv_len++;
828 }
829 bv.bv_val = ch_malloc( bv.bv_len + 1 );
830 ptr = lutil_strcopy( bv.bv_val, ibuf );
831 for (j=1; argv[j]; j++) {
832 if ( j ) *ptr++ = ' ';
833 ptr = lutil_strcopy( ptr, argv[j] );
834 }
835 ber_bvarray_add( out, &bv );
836 }
837 }
838 #endif /* HAVE_LTDL_H */
839