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