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 * 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 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 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 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 * 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 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 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 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 * 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 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 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 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 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 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 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