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