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