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 <ldap_pvt_thread.h>
19 * Note: if ltdl.h is not available, slapi should not be compiled
23 static int loadPlugin( Slapi_PBlock *, const char *, const char *, int,
24 SLAPI_FUNC *, lt_dlhandle * );
26 /* pointer to link list of extended objects */
27 static ExtendedOp *pGExtendedOps = NULL;
28 /* global plugins not associated with a specific backend */
29 static Slapi_PBlock *pGPlugins = NULL;
31 /*********************************************************************
32 * Function Name: newPlugin
34 * Description: This routine creates a new Slapi_PBlock structure,
35 * loads in the plugin module and executes the init
36 * function provided by the module.
38 * Input: type - type of the plugin, such as SASL, database, etc.
39 * path - the loadpath to load the module in
40 * initfunc - name of the plugin function to execute first
41 * argc - number of arguements
42 * argv[] - an array of char pointers point to
43 * the arguments passed in via
44 * the configuration file.
48 * Return Values: a pointer to a newly created Slapi_PBlock structrue or
49 * NULL - function failed
52 *********************************************************************/
62 Slapi_PBlock *pPlugin = NULL;
63 lt_dlhandle hdLoadHandle;
66 pPlugin = slapi_pblock_new();
67 if ( pPlugin == NULL ) {
72 rc = slapi_pblock_set( pPlugin, SLAPI_PLUGIN_TYPE, (void *)type );
73 if ( rc != LDAP_SUCCESS ) {
77 rc = slapi_pblock_set( pPlugin, SLAPI_PLUGIN_ARGC, (void *)argc );
78 if ( rc != LDAP_SUCCESS ) {
82 rc = slapi_pblock_set( pPlugin, SLAPI_PLUGIN_ARGV, (void *)argv );
83 if ( rc != LDAP_SUCCESS ) {
87 rc = loadPlugin( pPlugin, path, initfunc, TRUE, NULL, &hdLoadHandle );
94 if ( rc != LDAP_SUCCESS && pPlugin != NULL ) {
95 slapi_pblock_destroy( pPlugin );
102 /*********************************************************************
103 * Function Name: insertPlugin
105 * Description: insert the slapi_pblock structure to the end of the plugin
108 * Input: a pointer to a plugin slapi_pblock structure to be added to
113 * Return Values: LDAP_SUCCESS - successfully inserted.
117 *********************************************************************/
123 Slapi_PBlock *pTmpPB;
124 Slapi_PBlock *pSavePB;
125 int rc = LDAP_SUCCESS;
127 pTmpPB = ( be == NULL ) ? pGPlugins : (Slapi_PBlock *)(be->be_pb);
129 if ( pTmpPB == NULL ) {
131 be->be_pb = (void *)pPB;
135 while ( pTmpPB != NULL && rc == LDAP_SUCCESS ) {
137 rc = slapi_pblock_get( pTmpPB, SLAPI_IBM_PBLOCK,
139 if ( rc != LDAP_SUCCESS ) {
144 if ( rc == LDAP_SUCCESS ) {
145 rc = slapi_pblock_set( pSavePB, SLAPI_IBM_PBLOCK,
147 if ( rc != LDAP_SUCCESS ) {
156 /*********************************************************************
157 * Function Name: getAllPluginFuncs
159 * Description: get the desired type of function pointers defined
162 * Input: the type of the functions to get, such as pre-operation,etc.
166 * Return Values: this routine returns a pointer to an array of function
167 * pointers containing backend-specific plugin functions
168 * followed by global plugin functions
171 *********************************************************************/
176 SLAPI_FUNC **ppFuncPtrs )
179 Slapi_PBlock *pCurrentPB;
181 SLAPI_FUNC *pTmpFuncPtr;
183 int rc = LDAP_SUCCESS;
185 assert( ppFuncPtrs );
188 * First, count the plugins associated with a specific
192 pCurrentPB = (Slapi_PBlock *)be->be_pb;
194 while ( pCurrentPB != NULL && rc == LDAP_SUCCESS ) {
195 rc = slapi_pblock_get( pCurrentPB, functype, &FuncPtr );
196 if ( rc == LDAP_SUCCESS ) {
197 if ( FuncPtr != NULL ) {
200 rc = slapi_pblock_get( pCurrentPB,
201 SLAPI_IBM_PBLOCK, &pCurrentPB );
206 if ( rc != LDAP_SUCCESS ) {
211 * Then, count the global plugins.
213 pCurrentPB = pGPlugins;
215 while ( pCurrentPB != NULL && rc == LDAP_SUCCESS ) {
216 rc = slapi_pblock_get( pCurrentPB, functype, &FuncPtr );
217 if ( rc == LDAP_SUCCESS ) {
218 if ( FuncPtr != NULL ) {
221 rc = slapi_pblock_get( pCurrentPB,
222 SLAPI_IBM_PBLOCK, &pCurrentPB );
226 if ( rc != LDAP_SUCCESS ) {
237 * Now, build the function pointer array of backend-specific
238 * plugins followed by global plugins.
240 *ppFuncPtrs = pTmpFuncPtr =
241 (SLAPI_FUNC *)ch_malloc( ( numPB + 1 ) * sizeof(SLAPI_FUNC) );
242 if ( ppFuncPtrs == NULL ) {
248 pCurrentPB = (Slapi_PBlock *)be->be_pb;
250 while ( pCurrentPB != NULL && rc == LDAP_SUCCESS ) {
251 rc = slapi_pblock_get( pCurrentPB, functype, &FuncPtr );
252 if ( rc == LDAP_SUCCESS ) {
253 if ( FuncPtr != NULL ) {
254 *pTmpFuncPtr = FuncPtr;
257 rc = slapi_pblock_get( pCurrentPB,
258 SLAPI_IBM_PBLOCK, &pCurrentPB );
263 pCurrentPB = pGPlugins;
265 while ( pCurrentPB != NULL && rc == LDAP_SUCCESS ) {
266 rc = slapi_pblock_get( pCurrentPB, functype, &FuncPtr );
267 if ( rc == LDAP_SUCCESS ) {
268 if ( FuncPtr != NULL ) {
269 *pTmpFuncPtr = FuncPtr;
272 rc = slapi_pblock_get( pCurrentPB,
273 SLAPI_IBM_PBLOCK, &pCurrentPB );
276 *pTmpFuncPtr = NULL ;
279 if ( rc != LDAP_SUCCESS && *ppFuncPtrs != NULL ) {
280 ch_free( *ppFuncPtrs );
287 /*********************************************************************
288 * Function Name: createExtendedOp
290 * Description: Creates an extended operation structure and
291 * initializes the fields
293 * Return value: A newly allocated structure or NULL
294 ********************************************************************/
300 ret = (ExtendedOp *)ch_malloc(sizeof(ExtendedOp));
302 ret->ext_oid.bv_val = NULL;
303 ret->ext_oid.bv_len = 0;
304 ret->ext_func = NULL;
306 ret->ext_next = NULL;
313 /*********************************************************************
314 * Function Name: removeExtendedOp
316 * Description: This routine removes the ExtendedOp structures
317 * asscoiated with a particular extended operation
320 * Input: pBE - pointer to a backend structure
321 * opList - pointer to a linked list of extended
322 * operation structures
323 * pPB - pointer to a slapi parameter block
330 *********************************************************************/
337 ExtendedOp *pTmpExtOp, *backExtOp;
342 assert( pBE != NULL); /* unused */
344 assert( opList != NULL );
345 assert( pPB != NULL );
347 if ( *opList == NULL ) {
351 slapi_pblock_get( pPB, SLAPI_PLUGIN_EXT_OP_OIDLIST, &pTmpOIDs );
352 if ( pTmpOIDs == NULL ) {
356 for ( i = 0; pTmpOIDs[i] != NULL; i++ ) {
359 for ( ; pTmpExtOp != NULL; pTmpExtOp = pTmpExtOp->ext_next) {
361 rc = strcasecmp( pTmpExtOp->ext_oid.bv_val,
364 if ( backExtOp == NULL ) {
365 *opList = pTmpExtOp->ext_next;
368 = pTmpExtOp->ext_next;
371 ch_free( pTmpExtOp );
374 backExtOp = pTmpExtOp;
380 /*********************************************************************
381 * Function Name: newExtendedOp
383 * Description: This routine creates a new ExtendedOp structure, loads
384 * in the extended op module and put the extended op function address
385 * in the structure. The function will not be executed in
388 * Input: pBE - pointer to a backend structure
389 * opList - pointer to a linked list of extended
390 * operation structures
391 * pPB - pointer to a slapi parameter block
395 * Return Value: an LDAP return code
398 *********************************************************************/
405 ExtendedOp *pTmpExtOp = NULL;
411 if ( (*opList) == NULL ) {
412 *opList = createExtendedOp();
413 if ( (*opList) == NULL ) {
419 } else { /* Find the end of the list */
420 for ( pTmpExtOp = *opList; pTmpExtOp->ext_next != NULL;
421 pTmpExtOp = pTmpExtOp->ext_next )
423 pTmpExtOp->ext_next = createExtendedOp();
424 if ( pTmpExtOp->ext_next == NULL ) {
428 pTmpExtOp = pTmpExtOp->ext_next;
431 rc = slapi_pblock_get( pPB,SLAPI_PLUGIN_EXT_OP_OIDLIST, &pTmpOIDs );
432 if ( rc != LDAP_SUCCESS ) {
437 rc = slapi_pblock_get(pPB,SLAPI_PLUGIN_EXT_OP_FN, &tmpFunc);
443 if ( (pTmpOIDs == NULL) || (tmpFunc == NULL) ) {
448 for ( i = 0; pTmpOIDs[i] != NULL; i++ ) {
449 pTmpExtOp->ext_oid.bv_val = pTmpOIDs[i];
450 pTmpExtOp->ext_oid.bv_len = strlen( pTmpOIDs[i] );
451 pTmpExtOp->ext_func = tmpFunc;
452 pTmpExtOp->ext_be = pBE;
453 if ( pTmpOIDs[i + 1] != NULL ) {
454 pTmpExtOp->ext_next = createExtendedOp();
455 if ( pTmpExtOp->ext_next == NULL ) {
459 pTmpExtOp = pTmpExtOp->ext_next;
467 /*********************************************************************
468 * Function Name: getPluginFunc
470 * Description: This routine gets the function address for a given function
474 * funcName - name of the extended op function, ie. an OID.
476 * Output: pFuncAddr - the function address of the requested function name.
478 * Return Values: a pointer to a newly created ExtendOp structrue or
479 * NULL - function failed
482 *********************************************************************/
485 struct berval *reqoid,
486 SLAPI_FUNC *pFuncAddr )
488 ExtendedOp *pTmpExtOp;
490 assert( reqoid != NULL );
491 assert( pFuncAddr != NULL );
495 if ( pGExtendedOps == NULL ) {
499 pTmpExtOp = pGExtendedOps;
500 while ( pTmpExtOp != NULL ) {
503 rc = strcasecmp( reqoid->bv_val, pTmpExtOp->ext_oid.bv_val );
505 *pFuncAddr = pTmpExtOp->ext_func;
508 pTmpExtOp = pTmpExtOp->ext_next;
511 return ( *pFuncAddr == NULL ? 1 : 0 );
514 /***************************************************************************
515 * This function is similar to getPluginFunc above. except it returns one OID
516 * per call. It is called from root_dse_info (root_dse.c).
517 * The function is a modified version of get_supported_extop (file extended.c).
518 ***************************************************************************/
520 ns_get_supported_extop( int index )
524 for ( ext = pGExtendedOps ; ext != NULL && --index >= 0;
525 ext = ext->ext_next) {
533 return &ext->ext_oid ;
536 /*********************************************************************
537 * Function Name: loadPlugin
539 * Description: This routine loads the specified DLL, gets and executes the init function
543 * pPlugin - a pointer to a Slapi_PBlock struct which will be passed to
544 * the DLL init function.
545 * path - path name of the DLL to be load.
546 * initfunc - either the DLL initialization function or an OID of the
547 * loaded extended operation.
548 * doInit - if it is TRUE, execute the init function, otherwise, save the
549 * function address but not execute it.
551 * Output: pInitFunc - the function address of the loaded function. This param
552 * should be not be null if doInit is FALSE.
553 * pLdHandle - handle returned by lt_dlopen()
555 * Return Values: LDAP_SUCCESS, LDAP_LOCAL_ERROR
558 *********************************************************************/
562 Slapi_PBlock *pPlugin,
564 const char *initfunc,
566 SLAPI_FUNC *pInitFunc,
567 lt_dlhandle *pLdHandle )
569 int rc = LDAP_SUCCESS;
570 SLAPI_FUNC fpInitFunc = NULL;
575 return LDAP_LOCAL_ERROR;
578 /* load in the module */
579 *pLdHandle = lt_dlopen( path );
580 if ( *pLdHandle == NULL ) {
581 return LDAP_LOCAL_ERROR;
584 fpInitFunc = (SLAPI_FUNC)lt_dlsym( *pLdHandle, initfunc );
585 if ( fpInitFunc == NULL ) {
586 lt_dlclose( *pLdHandle );
587 return LDAP_LOCAL_ERROR;
590 if ( doInit == TRUE ) {
591 rc = ( *fpInitFunc )( pPlugin );
592 if ( rc != LDAP_SUCCESS ) {
593 lt_dlclose( *pLdHandle );
597 *pInitFunc = fpInitFunc;
604 * Special support for computed attribute plugins
614 SLAPI_FUNC *pGetPlugin = NULL, *tmpPlugin = NULL;
620 rc = getAllPluginFuncs( be, funcType, &tmpPlugin );
621 if ( rc != LDAP_SUCCESS || tmpPlugin == NULL ) {
622 /* Nothing to do, front-end should ignore. */
626 for ( pGetPlugin = tmpPlugin ; *pGetPlugin != NULL; pGetPlugin++ ) {
628 * FIXME: we should provide here a sort of sandbox,
629 * to protect from plugin faults; e.g. trap signals
630 * and longjump here, marking the plugin as unsafe for
631 * later executions ...
633 rc = (*pGetPlugin)(pPB);
636 * Only non-postoperation plugins abort processing on
637 * failure (confirmed with SLAPI specification).
639 if ( !SLAPI_PLUGIN_IS_POST_FN( funcType ) && rc != 0 ) {
644 slapi_ch_free( (void **)&tmpPlugin );
658 int numPluginArgc = 0;
659 char **ppPluginArgv = NULL;
663 "%s: line %d: missing arguments "
664 "in \"plugin <plugin_type> <lib_path> "
665 "<init_function> [<arguments>]\" line\n",
670 if ( strcasecmp( argv[1], "preoperation" ) == 0 ) {
671 iType = SLAPI_PLUGIN_PREOPERATION;
672 } else if ( strcasecmp( argv[1], "postoperation" ) == 0 ) {
673 iType = SLAPI_PLUGIN_POSTOPERATION;
674 } else if ( strcasecmp( argv[1], "extendedop" ) == 0 ) {
675 iType = SLAPI_PLUGIN_EXTENDEDOP;
676 } else if ( strcasecmp( argv[1], "object" ) == 0 ) {
677 iType = SLAPI_PLUGIN_OBJECT;
679 fprintf( stderr, "%s: line %d: invalid plugin type \"%s\".\n",
680 fname, lineno, argv[1] );
684 numPluginArgc = argc - 4;
685 if ( numPluginArgc > 0 ) {
686 ppPluginArgv = &argv[4];
691 if ( iType == SLAPI_PLUGIN_PREOPERATION ||
692 iType == SLAPI_PLUGIN_EXTENDEDOP ||
693 iType == SLAPI_PLUGIN_POSTOPERATION ||
694 iType == SLAPI_PLUGIN_OBJECT ) {
696 Slapi_PBlock *pPlugin;
698 pPlugin = newPlugin( iType, argv[2], argv[3],
699 numPluginArgc, ppPluginArgv );
700 if (pPlugin == NULL) {
704 if (iType == SLAPI_PLUGIN_EXTENDEDOP) {
705 rc = newExtendedOp(be, &pGExtendedOps, pPlugin);
706 if ( rc != LDAP_SUCCESS ) {
707 slapi_pblock_destroy( pPlugin );
712 rc = insertPlugin( be, pPlugin );
713 if ( rc != LDAP_SUCCESS ) {
714 if ( iType == SLAPI_PLUGIN_EXTENDEDOP ) {
715 removeExtendedOp( be, &pGExtendedOps, pPlugin );
717 slapi_pblock_destroy( pPlugin );
728 if ( ldap_pvt_thread_mutex_init( &slapi_hn_mutex ) ) {
732 if ( ldap_pvt_thread_mutex_init( &slapi_time_mutex ) ) {
736 if ( ldap_pvt_thread_mutex_init( &slapi_printmessage_mutex ) ) {
740 slapi_log_file = ch_strdup( LDAP_RUNDIR LDAP_DIRSEP "errors" );
741 if ( slapi_log_file == NULL ) {