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