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