2 * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
3 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6 * (C) Copyright IBM Corp. 1997,2002
7 * Redistribution and use in source and binary forms are permitted
8 * provided that this notice is preserved and that due credit is
9 * given to IBM Corporation. This software is provided ``as is''
10 * without express or implied warranty.
14 #include "slapi_common.h"
15 #include <ldap_pvt_thread.h>
20 * Note: if ltdl.h is not available, slapi should not be compiled
24 static int loadPlugin( Slapi_PBlock *, const char *, const char *, int,
25 SLAPI_FUNC *, lt_dlhandle * );
27 /* pointer to link list of extended objects */
28 static ExtendedOp *pGExtendedOps = NULL;
30 /*********************************************************************
31 * Function Name: newPlugin
33 * Description: This routine creates a new Slapi_PBlock structure,
34 * loads in the plugin module and executes the init
35 * function provided by the module.
37 * Input: type - type of the plugin, such as SASL, database, etc.
38 * path - the loadpath to load the module in
39 * initfunc - name of the plugin function to execute first
40 * argc - number of arguements
41 * argv[] - an array of char pointers point to
42 * the arguments passed in via
43 * the configuration file.
47 * Return Values: a pointer to a newly created Slapi_PBlock structrue or
48 * NULL - function failed
51 *********************************************************************/
61 Slapi_PBlock *pPlugin = NULL;
62 lt_dlhandle hdLoadHandle;
65 pPlugin = slapi_pblock_new();
66 if ( pPlugin == NULL ) {
71 rc = slapi_pblock_set( pPlugin, SLAPI_PLUGIN_TYPE, (void *)type );
72 if ( rc != LDAP_SUCCESS ) {
76 rc = slapi_pblock_set( pPlugin, SLAPI_PLUGIN_ARGC, (void *)argc );
77 if ( rc != LDAP_SUCCESS ) {
81 rc = slapi_pblock_set( pPlugin, SLAPI_PLUGIN_ARGV, (void *)argv );
82 if ( rc != LDAP_SUCCESS ) {
86 rc = loadPlugin( pPlugin, path, initfunc, TRUE, NULL, &hdLoadHandle );
89 if ( rc != LDAP_SUCCESS && pPlugin != NULL ) {
90 slapi_pblock_destroy( pPlugin );
97 /*********************************************************************
98 * Function Name: insertPlugin
100 * Description: insert the slapi_pblock structure to the end of the plugin
103 * Input: a pointer to a plugin slapi_pblock structure to be added to
108 * Return Values: LDAP_SUCCESS - successfully inserted.
112 *********************************************************************/
118 Slapi_PBlock *pTmpPB;
119 Slapi_PBlock *pSavePB;
120 int rc = LDAP_SUCCESS;
122 pTmpPB = (Slapi_PBlock *)(be->be_pb);
124 if ( pTmpPB == NULL ) {
125 be->be_pb = (void *)pPB;
127 while ( pTmpPB != NULL && rc == LDAP_SUCCESS ) {
129 rc = slapi_pblock_get( pTmpPB, SLAPI_IBM_PBLOCK,
131 if ( rc != LDAP_SUCCESS ) {
136 if ( rc == LDAP_SUCCESS ) {
137 rc = slapi_pblock_set( pSavePB, SLAPI_IBM_PBLOCK,
139 if ( rc != LDAP_SUCCESS ) {
148 /*********************************************************************
149 * Function Name: getAllPluginFuncs
151 * Description: get the desired type of function pointers defined
154 * Input: the type of the functions to get, such as pre-operation,etc.
158 * Return Values: this routine returns a pointer to an array of function
162 *********************************************************************/
167 SLAPI_FUNC **ppFuncPtrs )
170 Slapi_PBlock *pCurrentPB;
172 SLAPI_FUNC *pTmpFuncPtr;
174 int rc = LDAP_SUCCESS;
178 * No plugins supported if no backend (yet)
184 assert( ppFuncPtrs );
186 pCurrentPB = (Slapi_PBlock *)(be->be_pb);
188 if ( pCurrentPB == NULL ) {
190 * LDAP_OTHER is returned if no plugins are installed
196 while ( pCurrentPB != NULL && rc == LDAP_SUCCESS ) {
197 rc = slapi_pblock_get( pCurrentPB, functype, &FuncPtr );
198 if ( rc == LDAP_SUCCESS ) {
199 if ( FuncPtr != NULL ) {
202 rc = slapi_pblock_get( pCurrentPB,
203 SLAPI_IBM_PBLOCK, &pCurrentPB );
207 if ( rc != LDAP_SUCCESS ) {
217 *ppFuncPtrs = pTmpFuncPtr =
218 (SLAPI_FUNC *)ch_malloc( ( numPB + 1 ) * sizeof(SLAPI_FUNC) );
219 if ( ppFuncPtrs == NULL ) {
224 pCurrentPB = (Slapi_PBlock *)(be->be_pb);
225 while ( pCurrentPB != NULL && rc == LDAP_SUCCESS ) {
226 rc = slapi_pblock_get( pCurrentPB, functype, &FuncPtr );
227 if ( rc == LDAP_SUCCESS ) {
228 if ( FuncPtr != NULL ) {
229 *pTmpFuncPtr = FuncPtr;
232 rc = slapi_pblock_get( pCurrentPB,
233 SLAPI_IBM_PBLOCK, &pCurrentPB );
236 *pTmpFuncPtr = NULL ;
239 if ( rc != LDAP_SUCCESS && *ppFuncPtrs != NULL ) {
240 ch_free( *ppFuncPtrs );
247 /*********************************************************************
248 * Function Name: createExtendedOp
250 * Description: Creates an extended operation structure and
251 * initializes the fields
253 * Return value: A newly allocated structure or NULL
254 ********************************************************************/
260 ret = (ExtendedOp *)ch_malloc(sizeof(ExtendedOp));
262 ret->ext_oid.bv_val = NULL;
263 ret->ext_oid.bv_len = 0;
264 ret->ext_func = NULL;
266 ret->ext_next = NULL;
273 /*********************************************************************
274 * Function Name: removeExtendedOp
276 * Description: This routine removes the ExtendedOp structures
277 * asscoiated with a particular extended operation
280 * Input: pBE - pointer to a backend structure
281 * opList - pointer to a linked list of extended
282 * operation structures
283 * pPB - pointer to a slapi parameter block
290 *********************************************************************/
297 ExtendedOp *pTmpExtOp, *backExtOp;
302 assert( pBE != NULL); /* unused */
304 assert( opList != NULL );
305 assert( pPB != NULL );
307 if ( *opList == NULL ) {
311 slapi_pblock_get( pPB, SLAPI_PLUGIN_EXT_OP_OIDLIST, &pTmpOIDs );
312 if ( pTmpOIDs == NULL ) {
316 for ( i = 0; pTmpOIDs[i] != NULL; i++ ) {
319 for ( ; pTmpExtOp != NULL; pTmpExtOp = pTmpExtOp->ext_next) {
321 rc = strcasecmp( pTmpExtOp->ext_oid.bv_val,
324 if ( backExtOp == NULL ) {
325 *opList = pTmpExtOp->ext_next;
328 = pTmpExtOp->ext_next;
331 ch_free( pTmpExtOp );
334 backExtOp = pTmpExtOp;
340 /*********************************************************************
341 * Function Name: newExtendedOp
343 * Description: This routine creates a new ExtendedOp structure, loads
344 * in the extended op module and put the extended op function address
345 * in the structure. The function will not be executed in
348 * Input: pBE - pointer to a backend structure
349 * opList - pointer to a linked list of extended
350 * operation structures
351 * pPB - pointer to a slapi parameter block
355 * Return Value: an LDAP return code
358 *********************************************************************/
365 ExtendedOp *pTmpExtOp = NULL;
371 if ( (*opList) == NULL ) {
372 *opList = createExtendedOp();
373 if ( (*opList) == NULL ) {
379 } else { /* Find the end of the list */
380 for ( pTmpExtOp = *opList; pTmpExtOp->ext_next != NULL;
381 pTmpExtOp = pTmpExtOp->ext_next )
383 pTmpExtOp->ext_next = createExtendedOp();
384 if ( pTmpExtOp->ext_next == NULL ) {
388 pTmpExtOp = pTmpExtOp->ext_next;
391 rc = slapi_pblock_get( pPB,SLAPI_PLUGIN_EXT_OP_OIDLIST, &pTmpOIDs );
392 if ( rc != LDAP_SUCCESS ) {
397 rc = slapi_pblock_get(pPB,SLAPI_PLUGIN_EXT_OP_FN, &tmpFunc);
403 if ( (pTmpOIDs == NULL) || (tmpFunc == NULL) ) {
408 for ( i = 0; pTmpOIDs[i] != NULL; i++ ) {
409 pTmpExtOp->ext_oid.bv_val = pTmpOIDs[i];
410 pTmpExtOp->ext_oid.bv_len = strlen( pTmpOIDs[i] );
411 pTmpExtOp->ext_func = tmpFunc;
412 pTmpExtOp->ext_be = pBE;
413 if ( pTmpOIDs[i + 1] != NULL ) {
414 pTmpExtOp->ext_next = createExtendedOp();
415 if ( pTmpExtOp->ext_next == NULL ) {
419 pTmpExtOp = pTmpExtOp->ext_next;
427 /*********************************************************************
428 * Function Name: getPluginFunc
430 * Description: This routine gets the function address for a given function
434 * funcName - name of the extended op function, ie. an OID.
436 * Output: pFuncAddr - the function address of the requested function name.
438 * Return Values: a pointer to a newly created ExtendOp structrue or
439 * NULL - function failed
442 *********************************************************************/
445 struct berval *reqoid,
446 SLAPI_FUNC *pFuncAddr )
448 ExtendedOp *pTmpExtOp;
450 assert( reqoid != NULL );
451 assert( pFuncAddr != NULL );
455 if ( pGExtendedOps == NULL ) {
459 pTmpExtOp = pGExtendedOps;
460 while ( pTmpExtOp != NULL ) {
463 rc = strcasecmp( reqoid->bv_val, pTmpExtOp->ext_oid.bv_val );
465 *pFuncAddr = pTmpExtOp->ext_func;
468 pTmpExtOp = pTmpExtOp->ext_next;
471 return ( *pFuncAddr == NULL ? 1 : 0 );
474 /***************************************************************************
475 * This function is similar to getPluginFunc above. except it returns one OID
476 * per call. It is called from root_dse_info (root_dse.c).
477 * The function is a modified version of get_supported_extop (file extended.c).
478 ***************************************************************************/
480 ns_get_supported_extop( int index )
484 for ( ext = pGExtendedOps ; ext != NULL && --index >= 0;
485 ext = ext->ext_next) {
493 return &ext->ext_oid ;
496 /*********************************************************************
497 * Function Name: loadPlugin
499 * Description: This routine loads the specified DLL, gets and executes the init function
503 * pPlugin - a pointer to a Slapi_PBlock struct which will be passed to
504 * the DLL init function.
505 * path - path name of the DLL to be load.
506 * initfunc - either the DLL initialization function or an OID of the
507 * loaded extended operation.
508 * doInit - if it is TRUE, execute the init function, otherwise, save the
509 * function address but not execute it.
511 * Output: pInitFunc - the function address of the loaded function. This param
512 * should be not be null if doInit is FALSE.
513 * pLdHandle - handle returned by lt_dlopen()
515 * Return Values: LDAP_SUCCESS, LDAP_LOCAL_ERROR
518 *********************************************************************/
522 Slapi_PBlock *pPlugin,
524 const char *initfunc,
526 SLAPI_FUNC *pInitFunc,
527 lt_dlhandle *pLdHandle )
529 int rc = LDAP_SUCCESS;
530 SLAPI_FUNC fpInitFunc = NULL;
535 return LDAP_LOCAL_ERROR;
538 /* load in the module */
539 *pLdHandle = lt_dlopen( path );
540 if ( *pLdHandle == NULL ) {
541 return LDAP_LOCAL_ERROR;
544 fpInitFunc = (SLAPI_FUNC)lt_dlsym( *pLdHandle, initfunc );
545 if ( fpInitFunc == NULL ) {
546 lt_dlclose( *pLdHandle );
547 return LDAP_LOCAL_ERROR;
550 if ( doInit == TRUE ) {
551 rc = ( *fpInitFunc )( pPlugin );
552 if ( rc != LDAP_SUCCESS ) {
553 lt_dlclose( *pLdHandle );
557 *pInitFunc = fpInitFunc;
571 int rc = LDAP_SUCCESS;
572 SLAPI_FUNC *pGetPlugin = NULL, *tmpPlugin = NULL;
574 rc = getAllPluginFuncs(be, funcType, &tmpPlugin );
575 if ( rc != LDAP_SUCCESS || tmpPlugin == NULL ) {
579 for ( pGetPlugin = tmpPlugin ; *pGetPlugin != NULL; pGetPlugin++ ) {
581 * FIXME: we should provide here a sort of sandbox,
582 * to protect from plugin faults; e.g. trap signals
583 * and longjump here, marking the plugin as unsafe for
584 * later executions ...
586 rc = (*pGetPlugin)(pPB);
589 * Only non-postoperation plugins abort processing on
590 * failure (confirmed with SLAPI specification).
592 if ( !SLAPI_PLUGIN_IS_POST_FN( funcType ) && rc != 0 ) {
597 ch_free( tmpPlugin );
611 int numPluginArgc = 0;
612 char **ppPluginArgv = NULL;
616 "%s: line %d: missing arguments "
617 "in \"plugin <plugin_type> <lib_path> "
618 "<init_function> [<arguments>]\" line\n",
623 if ( strcasecmp( argv[1], "preoperation" ) == 0 ) {
624 iType = SLAPI_PLUGIN_PREOPERATION;
625 } else if ( strcasecmp( argv[1], "postoperation" ) == 0 ) {
626 iType = SLAPI_PLUGIN_POSTOPERATION;
627 } else if ( strcasecmp( argv[1], "extendedop" ) == 0 ) {
628 iType = SLAPI_PLUGIN_EXTENDEDOP;
629 } else if ( strcasecmp( argv[1], "opattrsp" ) == 0 ) {
630 iType = SLAPI_PLUGIN_OPATTR_SP;
632 fprintf( stderr, "%s: line %d: invalid plugin type \"%s\".\n",
633 fname, lineno, argv[1] );
637 numPluginArgc = argc - 4;
638 if ( numPluginArgc > 0 ) {
639 ppPluginArgv = &argv[4];
644 if ( iType == SLAPI_PLUGIN_PREOPERATION ||
645 iType == SLAPI_PLUGIN_EXTENDEDOP ||
646 iType == SLAPI_PLUGIN_POSTOPERATION ||
647 iType == SLAPI_PLUGIN_OPATTR_SP ) {
649 Slapi_PBlock *pPlugin;
651 pPlugin = newPlugin( iType, argv[2], argv[3],
652 numPluginArgc, ppPluginArgv );
653 if (pPlugin == NULL) {
657 if (iType == SLAPI_PLUGIN_EXTENDEDOP) {
658 rc = newExtendedOp(be, &pGExtendedOps, pPlugin);
659 if ( rc != LDAP_SUCCESS ) {
660 slapi_pblock_destroy( pPlugin );
665 rc = insertPlugin( be, pPlugin );
666 if ( rc != LDAP_SUCCESS ) {
667 if ( iType == SLAPI_PLUGIN_EXTENDEDOP ) {
668 removeExtendedOp( be, &pGExtendedOps, pPlugin );
670 slapi_pblock_destroy( pPlugin );
681 if ( ldap_pvt_thread_mutex_init( &slapi_hn_mutex ) ) {
685 if ( ldap_pvt_thread_mutex_init( &slapi_time_mutex ) ) {
689 if ( ldap_pvt_thread_mutex_init( &slapi_printmessage_mutex ) ) {
693 slapi_log_file = ch_strdup( LDAP_RUNDIR LDAP_DIRSEP "errors" );
694 if ( slapi_log_file == NULL ) {