]> git.sur5r.net Git - openldap/blob - servers/slapd/back-monitor/init.c
d00405d40a01b45d8ae7910a423906ab9cbbfca7
[openldap] / servers / slapd / back-monitor / init.c
1 /* init.c - initialize monitor backend */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2001-2004 The OpenLDAP Foundation.
6  * Portions Copyright 2001-2003 Pierangelo Masarati.
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 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 Pierangelo Masarati for inclusion
19  * in OpenLDAP Software.
20  */
21
22 #include "portable.h"
23
24 #include <stdio.h>
25 #include <ac/string.h>
26
27 #include <lutil.h>
28 #include "slap.h"
29 #include "lber_pvt.h"
30 #include "back-monitor.h"
31
32 #undef INTEGRATE_CORE_SCHEMA
33
34 /*
35  * used by many functions to add description to entries
36  *
37  * WARNING: be_monitor may change as new databases are added,
38  * so it should not be used outside monitor_back_db_init()
39  * until monitor_back_db_open is called.
40  */
41 BackendDB *be_monitor = NULL;
42
43 static struct monitor_subsys_t  **monitor_subsys = NULL;
44 static int                      monitor_subsys_opened = 0;
45
46 /*
47  * subsystem data
48  *
49  * the known subsystems are added to the subsystems
50  * array at backend initialization; other subsystems
51  * may be added by calling monitor_back_register_subsys()
52  * before the database is opened (e.g. by other backends
53  * or by overlays or modules).
54  */
55 static struct monitor_subsys_t known_monitor_subsys[] = {
56         { 
57                 SLAPD_MONITOR_BACKEND_NAME, 
58                 BER_BVNULL, BER_BVNULL, BER_BVNULL,
59                 MONITOR_F_PERSISTENT_CH,
60                 monitor_subsys_backend_init,
61                 NULL,   /* update */
62                 NULL,   /* create */
63                 NULL    /* modify */
64         }, { 
65                 SLAPD_MONITOR_CONN_NAME,
66                 BER_BVNULL, BER_BVNULL, BER_BVNULL,
67                 MONITOR_F_VOLATILE_CH,
68                 monitor_subsys_conn_init,
69                 monitor_subsys_conn_update,
70                 monitor_subsys_conn_create,
71                 NULL    /* modify */
72         }, { 
73                 SLAPD_MONITOR_DATABASE_NAME,    
74                 BER_BVNULL, BER_BVNULL, BER_BVNULL,
75                 MONITOR_F_PERSISTENT_CH,
76                 monitor_subsys_database_init,
77                 NULL,   /* update */
78                 NULL,   /* create */
79                 monitor_subsys_database_modify
80         }, { 
81                 SLAPD_MONITOR_LISTENER_NAME,    
82                 BER_BVNULL, BER_BVNULL, BER_BVNULL,
83                 MONITOR_F_PERSISTENT_CH,
84                 monitor_subsys_listener_init,
85                 NULL,   /* update */
86                 NULL,   /* create */
87                 NULL    /* modify */
88         }, { 
89                 SLAPD_MONITOR_LOG_NAME,
90                 BER_BVNULL, BER_BVNULL, BER_BVNULL,
91                 MONITOR_F_NONE,
92                 monitor_subsys_log_init,
93                 NULL,   /* update */
94                 NULL,   /* create */
95                 monitor_subsys_log_modify
96         }, { 
97                 SLAPD_MONITOR_OPS_NAME,
98                 BER_BVNULL, BER_BVNULL, BER_BVNULL,
99                 MONITOR_F_PERSISTENT_CH,
100                 monitor_subsys_ops_init,
101                 monitor_subsys_ops_update,
102                 NULL,   /* create */
103                 NULL,   /* modify */
104         }, { 
105                 SLAPD_MONITOR_OVERLAY_NAME,
106                 BER_BVNULL, BER_BVNULL, BER_BVNULL,
107                 MONITOR_F_PERSISTENT_CH,
108                 monitor_subsys_overlay_init,
109                 NULL,   /* update */
110                 NULL,   /* create */
111                 NULL,   /* modify */
112         }, { 
113                 SLAPD_MONITOR_SASL_NAME,        
114                 BER_BVNULL, BER_BVNULL, BER_BVNULL,
115                 MONITOR_F_NONE,
116                 NULL,   /* init */
117                 NULL,   /* update */
118                 NULL,   /* create */
119                 NULL    /* modify */
120         }, { 
121                 SLAPD_MONITOR_SENT_NAME,
122                 BER_BVNULL, BER_BVNULL, BER_BVNULL,
123                 MONITOR_F_PERSISTENT_CH,
124                 monitor_subsys_sent_init,
125                 monitor_subsys_sent_update,
126                 NULL,   /* create */
127                 NULL,   /* modify */
128         }, { 
129                 SLAPD_MONITOR_THREAD_NAME,      
130                 BER_BVNULL, BER_BVNULL, BER_BVNULL,
131                 MONITOR_F_PERSISTENT_CH,
132                 monitor_subsys_thread_init,
133                 monitor_subsys_thread_update,
134                 NULL,   /* create */
135                 NULL    /* modify */
136         }, { 
137                 SLAPD_MONITOR_TIME_NAME,
138                 BER_BVNULL, BER_BVNULL, BER_BVNULL,
139                 MONITOR_F_PERSISTENT_CH,
140                 monitor_subsys_time_init,
141                 monitor_subsys_time_update,
142                 NULL,   /* create */
143                 NULL,   /* modify */
144         }, { 
145                 SLAPD_MONITOR_TLS_NAME,
146                 BER_BVNULL, BER_BVNULL, BER_BVNULL,
147                 MONITOR_F_NONE,
148                 NULL,   /* init */
149                 NULL,   /* update */
150                 NULL,   /* create */
151                 NULL    /* modify */
152         }, { 
153                 SLAPD_MONITOR_RWW_NAME,
154                 BER_BVNULL, BER_BVNULL, BER_BVNULL,
155                 MONITOR_F_PERSISTENT_CH,
156                 monitor_subsys_rww_init,
157                 monitor_subsys_rww_update,
158                 NULL,   /* create */
159                 NULL    /* modify */
160         }, { NULL }
161 };
162
163 int
164 monitor_back_register_subsys( monitor_subsys_t *ms )
165 {
166         int     i = 0;
167
168         if ( monitor_subsys ) {
169                 for ( ; monitor_subsys[ i ] != NULL; i++ )
170                         /* just count'em */ ;
171         }
172
173         monitor_subsys = ch_realloc( monitor_subsys,
174                         ( 2 + i ) * sizeof( monitor_subsys_t * ) );
175
176         if ( monitor_subsys == NULL ) {
177                 return -1;
178         }
179
180         monitor_subsys[ i ] = ms;
181         monitor_subsys[ i + 1 ] = NULL;
182
183         /* if a subsystem is registered __AFTER__ subsystem 
184          * initialization (depending on the sequence the databases
185          * are listed in slapd.conf), init it */
186         if ( monitor_subsys_opened ) {
187
188                 /* FIXME: this should only be possible
189                  * if be_monitor is already initialized */
190                 assert( be_monitor );
191
192                 if ( ms->mss_open && ( *ms->mss_open )( be_monitor, ms ) ) {
193                         return -1;
194                 }
195
196                 ms->mss_flags |= MONITOR_F_OPENED;
197         }
198
199         return 0;
200 }
201
202 enum {
203         LIMBO_ENTRY,
204         LIMBO_ATTRS,
205         LIMBO_CB
206 };
207
208 typedef struct entry_limbo_t {
209         int                     el_type;
210         Entry                   *el_e;
211         Attribute               *el_a;
212         struct berval           el_ndn;
213         struct berval           el_base;
214         int                     el_scope;
215         struct berval           el_filter;
216         monitor_callback_t      *el_cb;
217         struct entry_limbo_t    *el_next;
218 } entry_limbo_t;
219
220 int
221 monitor_back_register_entry(
222                 Entry                   *e,
223                 monitor_callback_t      *cb )
224 {
225         monitor_info_t  *mi = ( monitor_info_t * )be_monitor->be_private;
226
227         assert( mi != NULL );
228         assert( e != NULL );
229         assert( e->e_private == NULL );
230         
231         if ( monitor_subsys_opened ) {
232                 Entry           *e_parent = NULL,
233                                 *e_new = NULL,
234                                 **ep = NULL;
235                 struct berval   pdn = BER_BVNULL;
236                 monitor_entry_t *mp = NULL,
237                                 *mp_parent = NULL;
238                 int             rc = 0;
239
240                 if ( monitor_cache_get( mi, &e->e_nname, &e_parent ) == 0 ) {
241                         /* entry exists */
242                         Debug( LDAP_DEBUG_ANY,
243                                 "monitor_back_register_entry(\"%s\"): "
244                                 "entry exists\n",
245                                 e->e_name.bv_val, 0, 0 );
246                         monitor_cache_release( mi, e_parent );
247                         return -1;
248                 }
249
250                 dnParent( &e->e_nname, &pdn );
251                 if ( monitor_cache_get( mi, &pdn, &e_parent ) != 0 ) {
252                         /* parent does not exist */
253                         Debug( LDAP_DEBUG_ANY,
254                                 "monitor_back_register_entry(\"%s\"): "
255                                 "parent \"%s\" not found\n",
256                                 e->e_name.bv_val, pdn.bv_val, 0 );
257                         return -1;
258                 }
259
260                 assert( e_parent->e_private != NULL );
261                 mp_parent = ( monitor_entry_t * )e_parent->e_private;
262
263                 if ( mp_parent->mp_flags & MONITOR_F_VOLATILE ) {
264                         /* entry is volatile; cannot append children */
265                         Debug( LDAP_DEBUG_ANY,
266                                 "monitor_back_register_entry(\"%s\"): "
267                                 "parent \"%s\" is volatile\n",
268                                 e->e_name.bv_val, e_parent->e_name.bv_val, 0 );
269                         rc = -1;
270                         goto done;
271                 }
272
273                 mp = monitor_entrypriv_create();
274                 if ( mp == NULL ) {
275                         Debug( LDAP_DEBUG_ANY,
276                                 "monitor_back_register_entry(\"%s\"): "
277                                 "monitor_entrypriv_create() failed\n",
278                                 e->e_name.bv_val, 0, 0 );
279                         rc = -1;
280                         goto done;
281                 }
282
283                 e_new = entry_dup( e );
284                 if ( e == NULL ) {
285                         Debug( LDAP_DEBUG_ANY,
286                                 "monitor_back_register_entry(\"%s\"): "
287                                 "entry_dup() failed\n",
288                                 e->e_name.bv_val, 0, 0 );
289                         rc = -1;
290                         goto done;
291                 }
292                 
293                 e_new->e_private = ( void * )mp;
294                 mp->mp_info = mp_parent->mp_info;
295                 mp->mp_flags = mp_parent->mp_flags | MONITOR_F_SUB;
296
297                 ep = &mp_parent->mp_children;
298                 for ( ; *ep; ) {
299                         mp_parent = ( monitor_entry_t * )(*ep)->e_private;
300                         ep = &mp_parent->mp_next;
301                 }
302                 *ep = e_new;
303
304                 if ( monitor_cache_add( mi, e_new ) ) {
305                         Debug( LDAP_DEBUG_ANY,
306                                 "monitor_back_register_entry(\"%s\"): "
307                                 "unable to add entry\n",
308                                 e->e_name.bv_val, 0, 0 );
309                         rc = -1;
310                         goto done;
311                 }
312
313 done:;
314                 if ( rc ) {
315                         if ( mp ) {
316                                 ch_free( mp );
317                         }
318                         if ( e_new ) {
319                                 e_new->e_private = NULL;
320                                 entry_free( e_new );
321                         }
322                 }
323
324                 if ( e_parent ) {
325                         monitor_cache_release( mi, e_parent );
326                 }
327
328         } else {
329                 entry_limbo_t   *elp, el = { 0 };
330
331                 el.el_type = LIMBO_ENTRY;
332
333                 el.el_e = entry_dup( e );
334                 if ( el.el_e == NULL ) {
335                         Debug( LDAP_DEBUG_ANY,
336                                 "monitor_back_register_entry(\"%s\"): "
337                                 "entry_dup() failed\n",
338                                 e->e_name.bv_val, 0, 0 );
339                         return -1;
340                 }
341                 
342                 el.el_cb = cb;
343
344                 elp = (entry_limbo_t *)ch_malloc( sizeof( entry_limbo_t ) );
345                 if ( elp ) {
346                         el.el_e->e_private = NULL;
347                         entry_free( el.el_e );
348                         return -1;
349                 }
350
351                 el.el_next = (entry_limbo_t *)mi->mi_entry_limbo;
352                 *elp = el;
353                 mi->mi_entry_limbo = (void *)elp;
354         }
355
356         return 0;
357 }
358
359 static int
360 monitor_filter2ndn_cb( Operation *op, SlapReply *rs )
361 {
362         if ( rs->sr_type == REP_SEARCH ) {
363                 struct berval   *ndn = op->o_callback->sc_private;
364                 
365                 ber_dupbv( ndn, &rs->sr_entry->e_nname );
366         }
367
368         return 0;
369 }
370
371 int
372 monitor_filter2ndn( struct berval *base, int scope, struct berval *filter,
373                 struct berval *ndn )
374 {
375         Connection      conn = { 0 };
376         char opbuf[OPERATION_BUFFER_SIZE];
377         Operation       *op;
378         SlapReply       rs = { 0 };
379         slap_callback   cb = { NULL, monitor_filter2ndn_cb, NULL, NULL };
380         AttributeName   anlist[ 2 ];
381         int             rc;
382
383         BER_BVZERO( ndn );
384
385         if ( be_monitor == NULL ) {
386                 return -1;
387         }
388
389         op = (Operation *)opbuf;
390         connection_fake_init( &conn, op, &conn );
391
392         op->o_tag = LDAP_REQ_SEARCH;
393
394         /* use global malloc for now */
395         op->o_tmpmemctx = NULL;
396         op->o_tmpmfuncs = &ch_mfuncs;
397
398         op->o_bd = be_monitor;
399         if ( base == NULL || BER_BVISNULL( base ) ) {
400                 ber_dupbv_x( &op->o_req_dn, &op->o_bd->be_suffix[ 0 ],
401                                 op->o_tmpmemctx );
402                 ber_dupbv_x( &op->o_req_ndn, &op->o_bd->be_nsuffix[ 0 ],
403                                 op->o_tmpmemctx );
404
405         } else {
406                 if ( dnPrettyNormal( NULL, base, &op->o_req_dn, &op->o_req_ndn,
407                                         op->o_tmpmemctx ) ) {
408                         /* error */
409                 }
410         }
411
412         op->o_callback = &cb;
413         cb.sc_private = (void *)ndn;
414
415         op->ors_scope = scope;
416         ber_dupbv_x( &op->ors_filterstr, filter, op->o_tmpmemctx );
417         op->ors_filter = str2filter_x( op, filter->bv_val );
418         op->ors_attrs = anlist;
419         BER_BVSTR( &anlist[ 0 ].an_name, LDAP_NO_ATTRS );
420         BER_BVZERO( &anlist[ 1 ].an_name );
421         op->ors_attrsonly = 0;
422         op->ors_tlimit = SLAP_NO_LIMIT;
423         op->ors_slimit = 1;
424         op->ors_limit = NULL;
425         op->ors_deref = LDAP_DEREF_NEVER;
426
427         op->o_nocaching = 1;
428         op->o_managedsait = SLAP_CONTROL_NONCRITICAL;
429
430         rc = op->o_bd->be_search( op, &rs );
431
432         filter_free_x( op, op->ors_filter );
433         op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
434         op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx );
435         op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );
436
437         if ( rc != 0 ) {
438                 return rc;
439         }
440
441         switch ( rs.sr_err ) {
442         case LDAP_SUCCESS:
443                 if ( BER_BVISNULL( ndn ) ) {
444                         rc = -1;
445                 }
446                 break;
447                         
448         case LDAP_SIZELIMIT_EXCEEDED:
449         default:
450                 if ( !BER_BVISNULL( ndn ) ) {
451                         ber_memfree( ndn->bv_val );
452                         BER_BVZERO( ndn );
453                 }
454                 rc = -1;
455                 break;
456         }
457
458         return rc;
459 }
460
461 int
462 monitor_back_register_entry_attrs(
463                 struct berval           *ndn_in,
464                 Attribute               *a,
465                 monitor_callback_t      *cb,
466                 struct berval           *base,
467                 int                     scope,
468                 struct berval           *filter )
469 {
470         monitor_info_t  *mi = ( monitor_info_t * )be_monitor->be_private;
471         struct berval   ndn = BER_BVNULL;
472
473         assert( mi != NULL );
474
475         if ( ndn_in != NULL ) {
476                 ndn = *ndn_in;
477         }
478
479         if ( a == NULL && cb == NULL ) {
480                 /* nothing to do */
481                 return -1;
482         }
483
484         if ( ( ndn_in == NULL || BER_BVISNULL( &ndn ) )
485                         && BER_BVISNULL( filter ) )
486         {
487                 /* need a filter */
488                 Debug( LDAP_DEBUG_ANY,
489                         "monitor_back_register_entry_*(\"\"): "
490                         "need a valid filter\n",
491                         0, 0, 0 );
492                 return -1;
493         }
494
495         if ( monitor_subsys_opened ) {
496                 Entry                   *e = NULL;
497                 Attribute               **atp = NULL;
498                 monitor_entry_t         *mp = NULL;
499                 monitor_callback_t      **mcp = NULL;
500                 int                     rc = 0;
501                 int                     freeit = 0;
502
503                 if ( BER_BVISNULL( &ndn ) ) {
504                         if ( monitor_filter2ndn( base, scope, filter, &ndn ) ) {
505                                 /* entry does not exist */
506                                 Debug( LDAP_DEBUG_ANY,
507                                         "monitor_back_register_entry_*(\"\"): "
508                                         "base=%s scope=%d filter=%s : "
509                                         "unable to find entry\n",
510                                         base->bv_val ? base->bv_val : "\"\"",
511                                         scope, filter->bv_val );
512                                 return -1;
513                         }
514
515                         freeit = 1;
516                 }
517
518                 if ( monitor_cache_get( mi, &ndn, &e ) != 0 ) {
519                         /* entry does not exist */
520                         Debug( LDAP_DEBUG_ANY,
521                                 "monitor_back_register_entry_*(\"%s\"): "
522                                 "entry does not exist\n",
523                                 ndn.bv_val, 0, 0 );
524                         rc = -1;
525                         goto done;
526                 }
527
528                 assert( e->e_private != NULL );
529                 mp = ( monitor_entry_t * )e->e_private;
530
531                 if ( mp->mp_flags & MONITOR_F_VOLATILE ) {
532                         /* entry is volatile; cannot append callback */
533                         Debug( LDAP_DEBUG_ANY,
534                                 "monitor_back_register_entry_*(\"%s\"): "
535                                 "entry is volatile\n",
536                                 e->e_name.bv_val, 0, 0 );
537                         rc = -1;
538                         goto done;
539                 }
540
541                 if ( a ) {
542                         for ( atp = &e->e_attrs; *atp; atp = &(*atp)->a_next )
543                                 /* just get to last */ ;
544
545                         *atp = attrs_dup( a );
546                         if ( *atp == NULL ) {
547                                 Debug( LDAP_DEBUG_ANY,
548                                         "monitor_back_register_entry_*(\"%s\"): "
549                                         "attrs_dup() failed\n",
550                                         e->e_name.bv_val, 0, 0 );
551                                 rc = -1;
552                                 goto done;
553                         }
554                 }
555
556                 if ( cb ) {
557                         for ( mcp = &mp->mp_cb; *mcp; mcp = &(*mcp)->mc_next )
558                                 /* go to tail */ ;
559                 
560                         /* NOTE: we do not clear cb->mc_next, so this function
561                          * can be used to append a list of callbacks */
562                         (*mcp) = cb;
563                 }
564
565 done:;
566                 if ( rc ) {
567                         if ( *atp ) {
568                                 attrs_free( *atp );
569                                 *atp = NULL;
570                         }
571                 }
572
573                 if ( freeit ) {
574                         ber_memfree( ndn.bv_val );
575                 }
576
577                 if ( e ) {
578                         monitor_cache_release( mi, e );
579                 }
580
581         } else {
582                 entry_limbo_t   *elp, el = { 0 };
583
584                 el.el_type = LIMBO_ATTRS;
585                 if ( !BER_BVISNULL( &ndn ) ) {
586                         ber_dupbv( &el.el_ndn, &ndn );
587                 }
588                 if ( !BER_BVISNULL( base ) ) {
589                         ber_dupbv( &el.el_base, base);
590                 }
591                 el.el_scope = scope;
592                 if ( !BER_BVISNULL( filter ) ) {
593                         ber_dupbv( &el.el_filter, filter );
594                 }
595
596                 el.el_a = attrs_dup( a );
597                 el.el_cb = cb;
598
599                 elp = (entry_limbo_t *)ch_malloc( sizeof( entry_limbo_t ) );
600                 if ( elp == NULL ) {
601                         attrs_free( a );
602                         return -1;
603                 }
604
605                 el.el_next = (entry_limbo_t *)mi->mi_entry_limbo;
606                 *elp = el;
607                 mi->mi_entry_limbo = (void *)elp;;
608         }
609
610         return 0;
611 }
612
613 int
614 monitor_back_register_entry_callback(
615                 struct berval           *ndn,
616                 monitor_callback_t      *cb,
617                 struct berval           *base,
618                 int                     scope,
619                 struct berval           *filter )
620 {
621         return monitor_back_register_entry_attrs( ndn, NULL, cb,
622                         base, scope, filter );
623 }
624
625 monitor_subsys_t *
626 monitor_back_get_subsys( const char *name )
627 {
628         if ( monitor_subsys != NULL ) {
629                 int     i;
630                 
631                 for ( i = 0; monitor_subsys[ i ] != NULL; i++ ) {
632                         if ( strcasecmp( monitor_subsys[ i ]->mss_name, name ) == 0 ) {
633                                 return monitor_subsys[ i ];
634                         }
635                 }
636         }
637
638         return NULL;
639 }
640
641 monitor_subsys_t *
642 monitor_back_get_subsys_by_dn( struct berval *ndn, int sub )
643 {
644         if ( monitor_subsys != NULL ) {
645                 int     i;
646
647                 if ( sub ) {
648                         for ( i = 0; monitor_subsys[ i ] != NULL; i++ ) {
649                                 if ( dnIsSuffix( ndn, &monitor_subsys[ i ]->mss_ndn ) ) {
650                                         return monitor_subsys[ i ];
651                                 }
652                         }
653
654                 } else {
655                         for ( i = 0; monitor_subsys[ i ] != NULL; i++ ) {
656                                 if ( dn_match( ndn, &monitor_subsys[ i ]->mss_ndn ) ) {
657                                         return monitor_subsys[ i ];
658                                 }
659                         }
660                 }
661         }
662
663         return NULL;
664 }
665
666 int
667 monitor_back_initialize(
668         BackendInfo     *bi
669 )
670 {
671         monitor_subsys_t        *ms;
672         static char             *controls[] = {
673                 LDAP_CONTROL_MANAGEDSAIT,
674                 LDAP_CONTROL_VALUESRETURNFILTER,
675                 NULL
676         };
677
678         bi->bi_controls = controls;
679
680         bi->bi_init = 0;
681         bi->bi_open = 0;
682         bi->bi_config = monitor_back_config;
683         bi->bi_close = 0;
684         bi->bi_destroy = 0;
685
686         bi->bi_db_init = monitor_back_db_init;
687         bi->bi_db_config = monitor_back_db_config;
688         bi->bi_db_open = monitor_back_db_open;
689         bi->bi_db_close = 0;
690         bi->bi_db_destroy = monitor_back_db_destroy;
691
692         bi->bi_op_bind = monitor_back_bind;
693         bi->bi_op_unbind = 0;
694         bi->bi_op_search = monitor_back_search;
695         bi->bi_op_compare = monitor_back_compare;
696         bi->bi_op_modify = monitor_back_modify;
697         bi->bi_op_modrdn = 0;
698         bi->bi_op_add = 0;
699         bi->bi_op_delete = 0;
700         bi->bi_op_abandon = 0;
701
702         bi->bi_extended = 0;
703
704         bi->bi_entry_release_rw = 0;
705         bi->bi_chk_referrals = 0;
706         bi->bi_operational = monitor_back_operational;
707
708         /*
709          * hooks for slap tools
710          */
711         bi->bi_tool_entry_open = 0;
712         bi->bi_tool_entry_close = 0;
713         bi->bi_tool_entry_first = 0;
714         bi->bi_tool_entry_next = 0;
715         bi->bi_tool_entry_get = 0;
716         bi->bi_tool_entry_put = 0;
717         bi->bi_tool_entry_reindex = 0;
718         bi->bi_tool_sync = 0;
719         bi->bi_tool_dn2id_get = 0;
720         bi->bi_tool_id2entry_get = 0;
721         bi->bi_tool_entry_modify = 0;
722
723         bi->bi_connection_init = 0;
724         bi->bi_connection_destroy = 0;
725
726         for ( ms = known_monitor_subsys; ms->mss_name != NULL; ms++ ) {
727                 if ( monitor_back_register_subsys( ms ) ) {
728                         return -1;
729                 }
730         }
731
732         return 0;
733 }
734
735 int
736 monitor_back_db_init(
737         BackendDB       *be
738 )
739 {
740         monitor_info_t  *mi;
741         int             i, rc;
742         struct berval   dn, ndn;
743         struct berval   bv;
744         const char      *text;
745
746         struct m_s {
747                 char    *name;
748                 char    *schema;
749                 slap_mask_t flags;
750                 int     offset;
751         } moc[] = {
752                 { "monitor", "( 1.3.6.1.4.1.4203.666.3.2 "
753                         "NAME 'monitor' "
754                         "DESC 'OpenLDAP system monitoring' "
755                         "SUP top STRUCTURAL "
756                         "MUST cn "
757                         "MAY ( "
758                                 "description "
759                                 "$ l "
760 #if 0   /* temporarily disabled */
761                                 "$ st "
762                                 "$ street "
763                                 "$ postalAddress "
764                                 "$ postalCode "
765 #endif
766                                 "$ seeAlso "
767                                 "$ labeledURI "
768                                 "$ monitoredInfo "
769                                 "$ managedInfo "
770                                 "$ monitorOverlay "
771                         ") )", SLAP_OC_OPERATIONAL|SLAP_OC_HIDE,
772                         offsetof(monitor_info_t, mi_oc_monitor) },
773                 { "monitorServer", "( 1.3.6.1.4.1.4203.666.3.7 "
774                         "NAME 'monitorServer' "
775                         "DESC 'Server monitoring root entry' "
776                         "SUP monitor STRUCTURAL )", SLAP_OC_OPERATIONAL|SLAP_OC_HIDE,
777                         offsetof(monitor_info_t, mi_oc_monitorServer) },
778                 { "monitorContainer", "( 1.3.6.1.4.1.4203.666.3.8 "
779                         "NAME 'monitorContainer' "
780                         "DESC 'monitor container class' "
781                         "SUP monitor STRUCTURAL )", SLAP_OC_OPERATIONAL|SLAP_OC_HIDE,
782                         offsetof(monitor_info_t, mi_oc_monitorContainer) },
783                 { "monitorCounterObject", "( 1.3.6.1.4.1.4203.666.3.9 "
784                         "NAME 'monitorCounterObject' "
785                         "DESC 'monitor counter class' "
786                         "SUP monitor STRUCTURAL )", SLAP_OC_OPERATIONAL|SLAP_OC_HIDE,
787                         offsetof(monitor_info_t, mi_oc_monitorCounterObject) },
788                 { "monitorOperation", "( 1.3.6.1.4.1.4203.666.3.10 "
789                         "NAME 'monitorOperation' "
790                         "DESC 'monitor operation class' "
791                         "SUP monitor STRUCTURAL )", SLAP_OC_OPERATIONAL|SLAP_OC_HIDE,
792                         offsetof(monitor_info_t, mi_oc_monitorOperation) },
793                 { "monitorConnection", "( 1.3.6.1.4.1.4203.666.3.11 "
794                         "NAME 'monitorConnection' "
795                         "DESC 'monitor connection class' "
796                         "SUP monitor STRUCTURAL )", SLAP_OC_OPERATIONAL|SLAP_OC_HIDE,
797                         offsetof(monitor_info_t, mi_oc_monitorConnection) },
798                 { "managedObject", "( 1.3.6.1.4.1.4203.666.3.12 "
799                         "NAME 'managedObject' "
800                         "DESC 'monitor managed entity class' "
801                         "SUP monitor STRUCTURAL )", SLAP_OC_OPERATIONAL|SLAP_OC_HIDE,
802                         offsetof(monitor_info_t, mi_oc_managedObject) },
803                 { "monitoredObject", "( 1.3.6.1.4.1.4203.666.3.14 "
804                         "NAME 'monitoredObject' "
805                         "DESC 'monitor monitored entity class' "
806                         "SUP monitor STRUCTURAL )", SLAP_OC_OPERATIONAL|SLAP_OC_HIDE,
807                         offsetof(monitor_info_t, mi_oc_monitoredObject) },
808                 { NULL, NULL, 0, -1 }
809         }, mat[] = {
810                 { "monitoredInfo", "( 1.3.6.1.4.1.4203.666.1.14 "
811                         "NAME 'monitoredInfo' "
812                         "DESC 'monitored info' "
813                         /* "SUP name " */
814                         "EQUALITY caseIgnoreMatch "
815                         "SUBSTR caseIgnoreSubstringsMatch "
816                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} "
817                         "NO-USER-MODIFICATION "
818                         "USAGE directoryOperation )", SLAP_AT_HIDE,
819                         offsetof(monitor_info_t, mi_ad_monitoredInfo) },
820                 { "managedInfo", "( 1.3.6.1.4.1.4203.666.1.15 "
821                         "NAME 'managedInfo' "
822                         "DESC 'monitor managed info' "
823                         "SUP name )", SLAP_AT_HIDE,
824                         offsetof(monitor_info_t, mi_ad_managedInfo) },
825                 { "monitorCounter", "( 1.3.6.1.4.1.4203.666.1.16 "
826                         "NAME 'monitorCounter' "
827                         "DESC 'monitor counter' "
828                         "EQUALITY integerMatch "
829                         "ORDERING integerOrderingMatch "
830                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 "
831                         "NO-USER-MODIFICATION "
832                         "USAGE directoryOperation )", SLAP_AT_HIDE,
833                         offsetof(monitor_info_t, mi_ad_monitorCounter) },
834                 { "monitorOpCompleted", "( 1.3.6.1.4.1.4203.666.1.17 "
835                         "NAME 'monitorOpCompleted' "
836                         "DESC 'monitor completed operations' "
837                         "SUP monitorCounter "
838                         "NO-USER-MODIFICATION "
839                         "USAGE directoryOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
840                         offsetof(monitor_info_t, mi_ad_monitorOpCompleted) },
841                 { "monitorOpInitiated", "( 1.3.6.1.4.1.4203.666.1.18 "
842                         "NAME 'monitorOpInitiated' "
843                         "DESC 'monitor initiated operations' "
844                         "SUP monitorCounter "
845                         "NO-USER-MODIFICATION "
846                         "USAGE directoryOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
847                         offsetof(monitor_info_t, mi_ad_monitorOpInitiated) },
848                 { "monitorConnectionNumber", "( 1.3.6.1.4.1.4203.666.1.19 "
849                         "NAME 'monitorConnectionNumber' "
850                         "DESC 'monitor connection number' "
851                         "SUP monitorCounter "
852                         "NO-USER-MODIFICATION "
853                         "USAGE directoryOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
854                         offsetof(monitor_info_t, mi_ad_monitorConnectionNumber) },
855                 { "monitorConnectionAuthzDN", "( 1.3.6.1.4.1.4203.666.1.20 "
856                         "NAME 'monitorConnectionAuthzDN' "
857                         "DESC 'monitor connection authorization DN' "
858                         /* "SUP distinguishedName " */
859                         "EQUALITY distinguishedNameMatch "
860                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 "
861                         "NO-USER-MODIFICATION "
862                         "USAGE directoryOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
863                         offsetof(monitor_info_t, mi_ad_monitorConnectionAuthzDN) },
864                 { "monitorConnectionLocalAddress", "( 1.3.6.1.4.1.4203.666.1.21 "
865                         "NAME 'monitorConnectionLocalAddress' "
866                         "DESC 'monitor connection local address' "
867                         "SUP monitoredInfo "
868                         "NO-USER-MODIFICATION "
869                         "USAGE directoryOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
870                         offsetof(monitor_info_t, mi_ad_monitorConnectionLocalAddress) },
871                 { "monitorConnectionPeerAddress", "( 1.3.6.1.4.1.4203.666.1.22 "
872                         "NAME 'monitorConnectionPeerAddress' "
873                         "DESC 'monitor connection peer address' "
874                         "SUP monitoredInfo "
875                         "NO-USER-MODIFICATION "
876                         "USAGE directoryOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
877                         offsetof(monitor_info_t, mi_ad_monitorConnectionPeerAddress) },
878                 { "monitorTimestamp", "( 1.3.6.1.4.1.4203.666.1.24 "
879                         "NAME 'monitorTimestamp' "
880                         "DESC 'monitor timestamp' "
881                         "EQUALITY generalizedTimeMatch "
882                         "ORDERING generalizedTimeOrderingMatch "
883                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 "
884                         "SINGLE-VALUE "
885                         "NO-USER-MODIFICATION "
886                         "USAGE directoryOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
887                         offsetof(monitor_info_t, mi_ad_monitorTimestamp) },
888                 { "monitorOverlay", "( 1.3.6.1.4.1.4203.666.1.27 "
889                         "NAME 'monitorOverlay' "
890                         "DESC 'name of overlays defined for a give database' "
891                         "SUP monitoredInfo "
892                         "NO-USER-MODIFICATION "
893                         "USAGE directoryOperation )", SLAP_AT_HIDE,
894                         offsetof(monitor_info_t, mi_ad_monitorOverlay) },
895                 { "readOnly", "( 1.3.6.1.4.1.4203.666.1.31 "
896                         "NAME 'readOnly' "
897                         "DESC 'read/write status of a given database' "
898                         "EQUALITY booleanMatch "
899                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 "
900                         "SINGLE-VALUE "
901                         "USAGE directoryOperation )", SLAP_AT_HIDE,
902                         offsetof(monitor_info_t, mi_ad_readOnly) },
903                 { "restrictedOperation", "( 1.3.6.1.4.1.4203.666.1.32 "
904                         "NAME 'restrictedOperation' "
905                         "DESC 'name of restricted operation for a given database' "
906                         "SUP managedInfo )", SLAP_AT_HIDE,
907                         offsetof(monitor_info_t, mi_ad_restrictedOperation ) },
908 #ifdef INTEGRATE_CORE_SCHEMA
909                 { NULL, NULL, 0, -1 },  /* description */
910                 { NULL, NULL, 0, -1 },  /* seeAlso */
911                 { NULL, NULL, 0, -1 },  /* l */
912                 { NULL, NULL, 0, -1 },  /* labeledURI */
913 #endif /* INTEGRATE_CORE_SCHEMA */
914                 { NULL, NULL, 0, -1 }
915         }, mat_core[] = {
916                 { "description", "( 2.5.4.13 "
917                         "NAME 'description' "
918                         "DESC 'RFC2256: descriptive information' "
919                         "EQUALITY caseIgnoreMatch "
920                         "SUBSTR caseIgnoreSubstringsMatch "
921                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{1024} )", 0,
922                         offsetof(monitor_info_t, mi_ad_description) },
923                 { "seeAlso", "( 2.5.4.34 "
924                         "NAME 'seeAlso' "
925                         "DESC 'RFC2256: DN of related object' "
926                         "SUP distinguishedName )", 0,
927                         offsetof(monitor_info_t, mi_ad_seeAlso) },
928                 { "l", "( 2.5.4.7 "
929                         "NAME ( 'l' 'localityName' ) "
930                         "DESC 'RFC2256: locality which this object resides in' "
931                         "SUP name )", 0,
932                         offsetof(monitor_info_t, mi_ad_l) },
933 #ifdef MONITOR_DEFINE_LABELEDURI
934                 { "labeledURI", "( 1.3.6.1.4.1.250.1.57 "
935                         "NAME 'labeledURI' "
936                         "DESC 'RFC2079: Uniform Resource Identifier with optional label' "
937                         "EQUALITY caseExactMatch "
938                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", 0,
939                         offsetof(monitor_info_t, mi_ad_labeledURI) },
940 #endif /* MONITOR_DEFINE_LABELEDURI */
941                 { NULL, NULL, 0, -1 }
942         };
943         
944         /*
945          * database monitor can be defined once only
946          */
947         if ( be_monitor ) {
948                 Debug( LDAP_DEBUG_ANY,
949                         "only one monitor backend is allowed\n", 0, 0, 0 );
950                 return( -1 );
951         }
952         be_monitor = be;
953
954         /* indicate system schema supported */
955         SLAP_BFLAGS(be) |= SLAP_BFLAG_MONITOR;
956
957         dn.bv_val = SLAPD_MONITOR_DN;
958         dn.bv_len = sizeof( SLAPD_MONITOR_DN ) - 1;
959
960         rc = dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL );
961         if( rc != LDAP_SUCCESS ) {
962                 Debug( LDAP_DEBUG_ANY,
963                         "unable to normalize monitor DN \"%s\"\n",
964                         SLAPD_MONITOR_DN, 0, 0 );
965                 return -1;
966         }
967
968         ber_dupbv( &bv, &dn );
969         ber_bvarray_add( &be->be_suffix, &bv );
970         ber_bvarray_add( &be->be_nsuffix, &ndn );
971
972         mi = ( monitor_info_t * )ch_calloc( sizeof( monitor_info_t ), 1 );
973         if ( mi == NULL ) {
974                 Debug( LDAP_DEBUG_ANY,
975                         "unable to initialize monitor backend\n", 0, 0, 0 );
976                 return -1;
977         }
978
979         memset( mi, 0, sizeof( monitor_info_t ) );
980
981         ldap_pvt_thread_mutex_init( &mi->mi_cache_mutex );
982
983         be->be_private = mi;
984         
985 #ifdef INTEGRATE_CORE_SCHEMA
986         /* prepare for schema integration */
987         for ( k = 0; mat[ k ].name != NULL; k++ );
988 #endif /* INTEGRATE_CORE_SCHEMA */
989
990         for ( i = 0; mat_core[ i ].name != NULL; i++ ) {
991                 AttributeDescription    **ad;
992                 const char              *text;
993
994                 ad = ((AttributeDescription **)&(((char *)mi)[ mat_core[ i ].offset ]));
995                 ad[ 0 ] = NULL;
996
997                 switch (slap_str2ad( mat_core[ i ].name, ad, &text ) ) {
998                 case LDAP_SUCCESS:
999                         break;
1000
1001 #ifdef INTEGRATE_CORE_SCHEMA
1002                 case LDAP_UNDEFINED_TYPE:
1003                         mat[ k ] = mat_core[ i ];
1004                         k++;
1005                         break;
1006 #endif /* INTEGRATE_CORE_SCHEMA */
1007
1008                 default:
1009                         Debug( LDAP_DEBUG_ANY,
1010                                 "monitor_back_db_init: %s: %s\n",
1011                                 mat_core[ i ].name, text, 0 );
1012                         return( -1 );
1013                 }
1014         }
1015
1016         /* schema integration */
1017         for ( i = 0; mat[ i ].name; i++ ) {
1018                 LDAPAttributeType       *at;
1019                 int                     code;
1020                 const char              *err;
1021                 AttributeDescription    **ad;
1022
1023                 at = ldap_str2attributetype( mat[ i ].schema, &code,
1024                         &err, LDAP_SCHEMA_ALLOW_ALL );
1025                 if ( !at ) {
1026                         Debug( LDAP_DEBUG_ANY, "monitor_back_db_init: "
1027                                 "in AttributeType \"%s\" %s before %s\n",
1028                                 mat[ i ].name, ldap_scherr2str(code), err );
1029                         return -1;
1030                 }
1031
1032                 if ( at->at_oid == NULL ) {
1033                         Debug( LDAP_DEBUG_ANY, "monitor_back_db_init: "
1034                                 "null OID for attributeType \"%s\"\n",
1035                                 mat[ i ].name, 0, 0 );
1036                         return -1;
1037                 }
1038
1039                 code = at_add(at, &err);
1040                 if ( code ) {
1041                         Debug( LDAP_DEBUG_ANY, "monitor_back_db_init: "
1042                                 "%s in attributeType \"%s\"\n",
1043                                 scherr2str(code), mat[ i ].name, 0 );
1044                         return -1;
1045                 }
1046                 ldap_memfree(at);
1047
1048                 ad = ((AttributeDescription **)&(((char *)mi)[ mat[ i ].offset ]));
1049                 ad[ 0 ] = NULL;
1050                 if ( slap_str2ad( mat[ i ].name, ad, &text ) ) {
1051                         Debug( LDAP_DEBUG_ANY,
1052                                 "monitor_back_db_init: %s\n", text, 0, 0 );
1053                         return -1;
1054                 }
1055
1056                 (*ad)->ad_type->sat_flags |= mat[ i ].flags;
1057         }
1058
1059         for ( i = 0; moc[ i ].name; i++ ) {
1060                 LDAPObjectClass         *oc;
1061                 int                     code;
1062                 const char              *err;
1063                 ObjectClass             *Oc;
1064
1065                 oc = ldap_str2objectclass(moc[ i ].schema, &code, &err,
1066                                 LDAP_SCHEMA_ALLOW_ALL );
1067                 if ( !oc ) {
1068                         Debug( LDAP_DEBUG_ANY,
1069                                 "unable to parse monitor objectclass \"%s\": "
1070                                 "%s before %s\n" , moc[ i ].name,
1071                                 ldap_scherr2str(code), err );
1072                         return -1;
1073                 }
1074
1075                 if ( oc->oc_oid == NULL ) {
1076                         Debug( LDAP_DEBUG_ANY,
1077                                 "objectclass \"%s\" has no OID\n" ,
1078                                 moc[ i ].name, 0, 0 );
1079                         return -1;
1080                 }
1081
1082                 code = oc_add(oc, 0, &err);
1083                 if ( code ) {
1084                         Debug( LDAP_DEBUG_ANY,
1085                                 "objectclass \"%s\": %s \"%s\"\n" ,
1086                                 moc[ i ].name, scherr2str(code), err );
1087                         return -1;
1088                 }
1089
1090                 ldap_memfree(oc);
1091
1092                 Oc = oc_find( moc[ i ].name );
1093                 if ( Oc == NULL ) {
1094                         Debug( LDAP_DEBUG_ANY, "monitor_back_db_init: "
1095                                         "unable to find objectClass %s "
1096                                         "(just added)\n", moc[ i ].name, 0, 0 );
1097                         return -1;
1098                 }
1099
1100                 Oc->soc_flags |= moc[ i ].flags;
1101
1102                 ((ObjectClass **)&(((char *)mi)[ moc[ i ].offset ]))[ 0 ] = Oc;
1103         }
1104
1105         return 0;
1106 }
1107
1108 int
1109 monitor_back_db_open(
1110         BackendDB       *be
1111 )
1112 {
1113         monitor_info_t          *mi = (monitor_info_t *)be->be_private;
1114         struct monitor_subsys_t **ms;
1115         Entry                   *e, **ep;
1116         monitor_entry_t         *mp;
1117         int                     i;
1118         char                    buf[ BACKMONITOR_BUFSIZE ],
1119                                 *end_of_line;
1120         struct berval           bv;
1121         struct tm               *tms;
1122 #ifdef HAVE_GMTIME_R
1123         struct tm               tm_buf;
1124 #endif
1125         static char             tmbuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];
1126
1127         assert( be_monitor );
1128         if ( be != be_monitor ) {
1129                 be_monitor = be;
1130         }
1131
1132         /*
1133          * Start
1134          */
1135 #ifndef HAVE_GMTIME_R
1136         ldap_pvt_thread_mutex_lock( &gmtime_mutex );
1137 #endif
1138 #ifdef HACK_LOCAL_TIME
1139 # ifdef HAVE_LOCALTIME_R
1140         tms = localtime_r( &starttime, &tm_buf );
1141 # else
1142         tms = localtime( &starttime );
1143 # endif /* HAVE_LOCALTIME_R */
1144         lutil_localtime( tmbuf, sizeof(tmbuf), tms, -timezone );
1145 #else /* !HACK_LOCAL_TIME */
1146 # ifdef HAVE_GMTIME_R
1147         tms = gmtime_r( &starttime, &tm_buf );
1148 # else
1149         tms = gmtime( &starttime );
1150 # endif /* HAVE_GMTIME_R */
1151         lutil_gentime( tmbuf, sizeof(tmbuf), tms );
1152 #endif /* !HACK_LOCAL_TIME */
1153 #ifndef HAVE_GMTIME_R
1154         ldap_pvt_thread_mutex_unlock( &gmtime_mutex );
1155 #endif
1156
1157         mi->mi_startTime.bv_val = tmbuf;
1158         mi->mi_startTime.bv_len = strlen( tmbuf );
1159
1160         if ( BER_BVISEMPTY( &be->be_rootdn ) ) {
1161                 BER_BVSTR( &mi->mi_creatorsName, SLAPD_ANONYMOUS );
1162         } else {
1163                 mi->mi_creatorsName = be->be_rootdn;
1164         }
1165
1166         /*
1167          * creates the "cn=Monitor" entry 
1168          */
1169         snprintf( buf, sizeof( buf ), 
1170                 "dn: %s\n"
1171                 "objectClass: %s\n"
1172                 "structuralObjectClass: %s\n"
1173                 "cn: Monitor\n"
1174                 "%s: This subtree contains monitoring/managing objects.\n"
1175                 "%s: This object contains information about this server.\n"
1176 #if 0
1177                 "%s: createTimestamp reflects the time this server instance was created.\n"
1178                 "%s: modifyTimestamp reflects the time this server instance was last accessed.\n"
1179 #endif
1180                 "creatorsName: %s\n"
1181                 "modifiersName: %s\n"
1182                 "createTimestamp: %s\n"
1183                 "modifyTimestamp: %s\n",
1184                 SLAPD_MONITOR_DN,
1185                 mi->mi_oc_monitorServer->soc_cname.bv_val,
1186                 mi->mi_oc_monitorServer->soc_cname.bv_val,
1187                 mi->mi_ad_description->ad_cname.bv_val,
1188                 mi->mi_ad_description->ad_cname.bv_val,
1189 #if 0
1190                 mi->mi_ad_description->ad_cname.bv_val,
1191                 mi->mi_ad_description->ad_cname.bv_val,
1192 #endif
1193                 mi->mi_creatorsName.bv_val,
1194                 mi->mi_creatorsName.bv_val,
1195                 mi->mi_startTime.bv_val,
1196                 mi->mi_startTime.bv_val );
1197
1198         e = str2entry( buf );
1199         if ( e == NULL) {
1200                 Debug( LDAP_DEBUG_ANY,
1201                         "unable to create \"%s\" entry\n",
1202                         SLAPD_MONITOR_DN, 0, 0 );
1203                 return( -1 );
1204         }
1205
1206         bv.bv_val = (char *) Versionstr;
1207         end_of_line = strchr( Versionstr, '\n' );
1208         if ( end_of_line ) {
1209                 bv.bv_len = end_of_line - Versionstr;
1210         } else {
1211                 bv.bv_len = strlen( Versionstr );
1212         }
1213
1214         if ( attr_merge_normalize_one( e, mi->mi_ad_monitoredInfo,
1215                                 &bv, NULL ) ) {
1216                 Debug( LDAP_DEBUG_ANY,
1217                         "unable to add monitoredInfo to \"%s\" entry\n",
1218                         SLAPD_MONITOR_DN, 0, 0 );
1219                 return( -1 );
1220         }
1221
1222         if ( mi->mi_l.bv_len ) {
1223                 if ( attr_merge_normalize_one( e, mi->mi_ad_l, &mi->mi_l, NULL ) ) {
1224                         Debug( LDAP_DEBUG_ANY,
1225                                 "unable to add locality to \"%s\" entry\n",
1226                                 SLAPD_MONITOR_DN, 0, 0 );
1227                         return( -1 );
1228                 }
1229         }
1230
1231         mp = monitor_entrypriv_create();
1232         if ( mp == NULL ) {
1233                 return -1;
1234         }
1235         e->e_private = ( void * )mp;
1236         ep = &mp->mp_children;
1237
1238         if ( monitor_cache_add( mi, e ) ) {
1239                 Debug( LDAP_DEBUG_ANY,
1240                         "unable to add entry \"%s\" to cache\n",
1241                         SLAPD_MONITOR_DN, 0, 0 );
1242                 return -1;
1243         }
1244
1245         /*      
1246          * Create all the subsystem specific entries
1247          */
1248         for ( i = 0; monitor_subsys[ i ] != NULL; i++ ) {
1249                 int             len = strlen( monitor_subsys[ i ]->mss_name );
1250                 struct berval   dn;
1251                 int             rc;
1252
1253                 dn.bv_len = len + sizeof( "cn=" ) - 1;
1254                 dn.bv_val = ch_calloc( sizeof( char ), dn.bv_len + 1 );
1255                 strcpy( dn.bv_val, "cn=" );
1256                 strcat( dn.bv_val, monitor_subsys[ i ]->mss_name );
1257                 rc = dnPretty( NULL, &dn, &monitor_subsys[ i ]->mss_rdn, NULL );
1258                 free( dn.bv_val );
1259                 if ( rc != LDAP_SUCCESS ) {
1260                         Debug( LDAP_DEBUG_ANY,
1261                                 "monitor RDN \"%s\" is invalid\n", 
1262                                 dn.bv_val, 0, 0 );
1263                         return( -1 );
1264                 }
1265
1266                 dn.bv_len += sizeof( SLAPD_MONITOR_DN ); /* 1 for the , */
1267                 dn.bv_val = ch_malloc( dn.bv_len + 1 );
1268                 strcpy( dn.bv_val , monitor_subsys[ i ]->mss_rdn.bv_val );
1269                 strcat( dn.bv_val, "," SLAPD_MONITOR_DN );
1270                 rc = dnPrettyNormal( NULL, &dn, &monitor_subsys[ i ]->mss_dn,
1271                         &monitor_subsys[ i ]->mss_ndn, NULL );
1272                 free( dn.bv_val );
1273                 if ( rc != LDAP_SUCCESS ) {
1274                         Debug( LDAP_DEBUG_ANY,
1275                                 "monitor DN \"%s\" is invalid\n", 
1276                                 dn.bv_val, 0, 0 );
1277                         return( -1 );
1278                 }
1279
1280                 snprintf( buf, sizeof( buf ),
1281                                 "dn: %s\n"
1282                                 "objectClass: %s\n"
1283                                 "structuralObjectClass: %s\n"
1284                                 "cn: %s\n"
1285                                 "creatorsName: %s\n"
1286                                 "modifiersName: %s\n"
1287                                 "createTimestamp: %s\n"
1288                                 "modifyTimestamp: %s\n",
1289                                 monitor_subsys[ i ]->mss_dn.bv_val,
1290                                 mi->mi_oc_monitorContainer->soc_cname.bv_val,
1291                                 mi->mi_oc_monitorContainer->soc_cname.bv_val,
1292                                 monitor_subsys[ i ]->mss_name,
1293                                 mi->mi_creatorsName.bv_val,
1294                                 mi->mi_creatorsName.bv_val,
1295                                 mi->mi_startTime.bv_val,
1296                                 mi->mi_startTime.bv_val );
1297                 
1298                 e = str2entry( buf );
1299                 
1300                 if ( e == NULL) {
1301                         Debug( LDAP_DEBUG_ANY,
1302                                 "unable to create \"%s\" entry\n", 
1303                                 monitor_subsys[ i ]->mss_dn.bv_val, 0, 0 );
1304                         return( -1 );
1305                 }
1306
1307                 mp = monitor_entrypriv_create();
1308                 if ( mp == NULL ) {
1309                         return -1;
1310                 }
1311                 e->e_private = ( void * )mp;
1312                 mp->mp_info = monitor_subsys[ i ];
1313                 mp->mp_flags = monitor_subsys[ i ]->mss_flags;
1314
1315                 if ( monitor_cache_add( mi, e ) ) {
1316                         Debug( LDAP_DEBUG_ANY,
1317                                 "unable to add entry \"%s\" to cache\n",
1318                                 monitor_subsys[ i ]->mss_dn.bv_val, 0, 0 );
1319                         return -1;
1320                 }
1321
1322                 *ep = e;
1323                 ep = &mp->mp_next;
1324         }
1325
1326         assert( be );
1327
1328         be->be_private = mi;
1329         
1330         /*
1331          * opens the monitor backend subsystems
1332          */
1333         for ( ms = monitor_subsys; ms[ 0 ] != NULL; ms++ ) {
1334                 if ( ms[ 0 ]->mss_open && ( *ms[ 0 ]->mss_open )( be, ms[ 0 ] ) )
1335                 {
1336                         return( -1 );
1337                 }
1338                 ms[ 0 ]->mss_flags |= MONITOR_F_OPENED;
1339         }
1340
1341         monitor_subsys_opened = 1;
1342
1343         if ( mi->mi_entry_limbo ) {
1344                 entry_limbo_t   *el = (entry_limbo_t *)mi->mi_entry_limbo;
1345
1346                 for ( ; el; ) {
1347                         entry_limbo_t   *tmp;
1348
1349                         switch ( el->el_type ) {
1350                         case LIMBO_ENTRY:
1351                                 monitor_back_register_entry(
1352                                                 el->el_e,
1353                                                 el->el_cb );
1354                                 break;
1355
1356                         case LIMBO_ATTRS:
1357                                 monitor_back_register_entry_attrs(
1358                                                 &el->el_ndn,
1359                                                 el->el_a,
1360                                                 el->el_cb,
1361                                                 &el->el_base,
1362                                                 el->el_scope,
1363                                                 &el->el_filter );
1364                                 break;
1365
1366                         case LIMBO_CB:
1367                                 monitor_back_register_entry_callback(
1368                                                 &el->el_ndn,
1369                                                 el->el_cb,
1370                                                 &el->el_base,
1371                                                 el->el_scope,
1372                                                 &el->el_filter );
1373                                 break;
1374
1375                         default:
1376                                 assert( 0 );
1377                         }
1378
1379                         if ( el->el_e ) {
1380                                 entry_free( el->el_e );
1381                         }
1382                         if ( el->el_a ) {
1383                                 attrs_free( el->el_a );
1384                         }
1385                         if ( !BER_BVISNULL( &el->el_ndn ) ) {
1386                                 ber_memfree( el->el_ndn.bv_val );
1387                         }
1388                         if ( !BER_BVISNULL( &el->el_base ) ) {
1389                                 ber_memfree( el->el_base.bv_val );
1390                         }
1391                         if ( !BER_BVISNULL( &el->el_filter ) ) {
1392                                 ber_memfree( el->el_filter.bv_val );
1393                         }
1394
1395                         tmp = el;
1396                         el = el->el_next;
1397                         ch_free( tmp );
1398                 }
1399
1400                 mi->mi_entry_limbo = NULL;
1401         }
1402
1403         return( 0 );
1404 }
1405
1406 int
1407 monitor_back_config(
1408         BackendInfo     *bi,
1409         const char      *fname,
1410         int             lineno,
1411         int             argc,
1412         char            **argv
1413 )
1414 {
1415         /*
1416          * eventually, will hold backend specific configuration parameters
1417          */
1418         return SLAP_CONF_UNKNOWN;
1419 }
1420
1421 int
1422 monitor_back_db_config(
1423         Backend     *be,
1424         const char  *fname,
1425         int         lineno,
1426         int         argc,
1427         char        **argv
1428 )
1429 {
1430         monitor_info_t  *mi = ( monitor_info_t * )be->be_private;
1431
1432         /*
1433          * eventually, will hold database specific configuration parameters
1434          */
1435         if ( strcasecmp( argv[ 0 ], "l" ) == 0 ) {
1436                 if ( argc != 2 ) {
1437                         return 1;
1438                 }
1439                 
1440                 ber_str2bv( argv[ 1 ], 0, 1, &mi->mi_l );
1441
1442         } else {
1443                 return SLAP_CONF_UNKNOWN;
1444         }
1445
1446         return( 0 );
1447 }
1448
1449 int
1450 monitor_back_db_destroy(
1451         BackendDB       *be
1452 )
1453 {
1454         /*
1455          * FIXME: destroys all the data
1456          */
1457         return 0;
1458 }
1459
1460 #if SLAPD_MONITOR == SLAPD_MOD_DYNAMIC
1461
1462 /* conditionally define the init_module() function */
1463 SLAP_BACKEND_INIT_MODULE( monitor )
1464
1465 #endif /* SLAPD_MONITOR == SLAPD_MOD_DYNAMIC */
1466