1 /*        $NetBSD: init.c,v 1.3 2021/08/14 16:15:00 christos Exp $    */
2 
3 /* init.c - initialize monitor backend */
4 /* $OpenLDAP$ */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 2001-2021 The OpenLDAP Foundation.
8  * Portions Copyright 2001-2003 Pierangelo Masarati.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted only as authorized by the OpenLDAP
13  * Public License.
14  *
15  * A copy of this license is available in file LICENSE in the
16  * top-level directory of the distribution or, alternatively, at
17  * <http://www.OpenLDAP.org/license.html>.
18  */
19 /* ACKNOWLEDGEMENTS:
20  * This work was initially developed by Pierangelo Masarati for inclusion
21  * in OpenLDAP Software.
22  */
23 
24 #include <sys/cdefs.h>
25 __RCSID("$NetBSD: init.c,v 1.3 2021/08/14 16:15:00 christos Exp $");
26 
27 #include "portable.h"
28 
29 #include <stdio.h>
30 #include <ac/string.h>
31 
32 #include <lutil.h>
33 #include "slap.h"
34 #include "slap-config.h"
35 #include "lber_pvt.h"
36 #include "back-monitor.h"
37 
38 #include "slap-config.h"
39 
40 #undef INTEGRATE_CORE_SCHEMA
41 
42 /*
43  * used by many functions to add description to entries
44  *
45  * WARNING: be_monitor may change as new databases are added,
46  * so it should not be used outside monitor_back_db_init()
47  * until monitor_back_db_open is called.
48  */
49 BackendDB                     *be_monitor;
50 
51 static struct monitor_subsys_t          **monitor_subsys;
52 static int                              monitor_subsys_opened;
53 static monitor_info_t                   monitor_info;
54 static const monitor_extra_t monitor_extra = {
55           monitor_back_is_configured,
56           monitor_back_get_subsys,
57           monitor_back_get_subsys_by_dn,
58 
59           monitor_back_register_subsys,
60           monitor_back_register_backend,
61           monitor_back_register_database,
62           monitor_back_register_overlay_info,
63           monitor_back_register_overlay,
64           monitor_back_register_entry,
65           monitor_back_register_entry_parent,
66           monitor_back_register_entry_attrs,
67           monitor_back_register_entry_callback,
68 
69           monitor_back_unregister_entry,
70           monitor_back_unregister_entry_parent,
71           monitor_back_unregister_entry_attrs,
72           monitor_back_unregister_entry_callback,
73 
74           monitor_back_entry_stub,
75           monitor_back_entrypriv_create,
76           monitor_back_register_subsys_late,
77           monitor_back_entry_get_unlocked
78 };
79 
80 
81 /*
82  * subsystem data
83  *
84  * the known subsystems are added to the subsystems
85  * array at backend initialization; other subsystems
86  * may be added by calling monitor_back_register_subsys()
87  * before the database is opened (e.g. by other backends
88  * or by overlays or modules).
89  */
90 static struct monitor_subsys_t known_monitor_subsys[] = {
91           {
92                     SLAPD_MONITOR_BACKEND_NAME,
93                     BER_BVNULL, BER_BVNULL, BER_BVNULL,
94                     { BER_BVC( "This subsystem contains information about available backends." ),
95                               BER_BVNULL },
96                     MONITOR_F_PERSISTENT_CH,
97                     monitor_subsys_backend_init,
98                     NULL,     /* destroy */
99                     NULL,   /* update */
100                     NULL,   /* create */
101                     NULL      /* modify */
102           }, {
103                     SLAPD_MONITOR_CONN_NAME,
104                     BER_BVNULL, BER_BVNULL, BER_BVNULL,
105                     { BER_BVC( "This subsystem contains information about connections." ),
106                               BER_BVNULL },
107                     MONITOR_F_VOLATILE_CH,
108                     monitor_subsys_conn_init,
109                     NULL,     /* destroy */
110                     NULL,   /* update */
111                     NULL,   /* create */
112                     NULL      /* modify */
113           }, {
114                     SLAPD_MONITOR_DATABASE_NAME,
115                     BER_BVNULL, BER_BVNULL, BER_BVNULL,
116                     { BER_BVC( "This subsystem contains information about configured databases." ),
117                               BER_BVNULL },
118                     MONITOR_F_PERSISTENT_CH,
119                     monitor_subsys_database_init,
120                     NULL,     /* destroy */
121                     NULL,   /* update */
122                     NULL,   /* create */
123                     NULL      /* modify */
124           }, {
125                     SLAPD_MONITOR_LISTENER_NAME,
126                     BER_BVNULL, BER_BVNULL, BER_BVNULL,
127                     { BER_BVC( "This subsystem contains information about active listeners." ),
128                               BER_BVNULL },
129                     MONITOR_F_PERSISTENT_CH,
130                     monitor_subsys_listener_init,
131                     NULL,     /* destroy */
132                     NULL,     /* update */
133                     NULL,     /* create */
134                     NULL      /* modify */
135           }, {
136                     SLAPD_MONITOR_LOG_NAME,
137                     BER_BVNULL, BER_BVNULL, BER_BVNULL,
138                     { BER_BVC( "This subsystem contains information about logging." ),
139                               BER_BVC( "Set the attribute \"managedInfo\" to the desired log levels." ),
140                               BER_BVNULL },
141                     MONITOR_F_NONE,
142                     monitor_subsys_log_init,
143                     NULL,     /* destroy */
144                     NULL,     /* update */
145                     NULL,   /* create */
146                     NULL,     /* modify */
147           }, {
148                     SLAPD_MONITOR_OPS_NAME,
149                     BER_BVNULL, BER_BVNULL, BER_BVNULL,
150                     { BER_BVC( "This subsystem contains information about performed operations." ),
151                               BER_BVNULL },
152                     MONITOR_F_PERSISTENT_CH,
153                     monitor_subsys_ops_init,
154                     NULL,     /* destroy */
155                     NULL,     /* update */
156                     NULL,   /* create */
157                     NULL,     /* modify */
158           }, {
159                     SLAPD_MONITOR_OVERLAY_NAME,
160                     BER_BVNULL, BER_BVNULL, BER_BVNULL,
161                     { BER_BVC( "This subsystem contains information about available overlays." ),
162                               BER_BVNULL },
163                     MONITOR_F_PERSISTENT_CH,
164                     monitor_subsys_overlay_init,
165                     NULL,     /* destroy */
166                     NULL,     /* update */
167                     NULL,   /* create */
168                     NULL,     /* modify */
169           }, {
170                     SLAPD_MONITOR_SASL_NAME,
171                     BER_BVNULL, BER_BVNULL, BER_BVNULL,
172                     { BER_BVC( "This subsystem contains information about SASL." ),
173                               BER_BVNULL },
174                     MONITOR_F_NONE,
175                     NULL,   /* init */
176                     NULL,     /* destroy */
177                     NULL,   /* update */
178                     NULL,   /* create */
179                     NULL      /* modify */
180           }, {
181                     SLAPD_MONITOR_SENT_NAME,
182                     BER_BVNULL, BER_BVNULL, BER_BVNULL,
183                     { BER_BVC( "This subsystem contains statistics." ),
184                               BER_BVNULL },
185                     MONITOR_F_PERSISTENT_CH,
186                     monitor_subsys_sent_init,
187                     NULL,     /* destroy */
188                     NULL,   /* update */
189                     NULL,   /* create */
190                     NULL,     /* modify */
191           }, {
192                     SLAPD_MONITOR_THREAD_NAME,
193                     BER_BVNULL, BER_BVNULL, BER_BVNULL,
194                     { BER_BVC( "This subsystem contains information about threads." ),
195                               BER_BVNULL },
196                     MONITOR_F_PERSISTENT_CH,
197                     monitor_subsys_thread_init,
198                     NULL,     /* destroy */
199                     NULL,   /* update */
200                     NULL,   /* create */
201                     NULL      /* modify */
202           }, {
203                     SLAPD_MONITOR_TIME_NAME,
204                     BER_BVNULL, BER_BVNULL, BER_BVNULL,
205                     { BER_BVC( "This subsystem contains information about time." ),
206                               BER_BVNULL },
207                     MONITOR_F_PERSISTENT_CH,
208                     monitor_subsys_time_init,
209                     NULL,     /* destroy */
210                     NULL,   /* update */
211                     NULL,   /* create */
212                     NULL,     /* modify */
213           }, {
214                     SLAPD_MONITOR_TLS_NAME,
215                     BER_BVNULL, BER_BVNULL, BER_BVNULL,
216                     { BER_BVC( "This subsystem contains information about TLS." ),
217                               BER_BVNULL },
218                     MONITOR_F_NONE,
219                     NULL,   /* init */
220                     NULL,     /* destroy */
221                     NULL,   /* update */
222                     NULL,   /* create */
223                     NULL      /* modify */
224           }, {
225                     SLAPD_MONITOR_RWW_NAME,
226                     BER_BVNULL, BER_BVNULL, BER_BVNULL,
227                     { BER_BVC( "This subsystem contains information about read/write waiters." ),
228                               BER_BVNULL },
229                     MONITOR_F_PERSISTENT_CH,
230                     monitor_subsys_rww_init,
231                     NULL,     /* destroy */
232                     NULL,   /* update */
233                     NULL,     /* create */
234                     NULL      /* modify */
235           }, { NULL }
236 };
237 
238 int
monitor_subsys_is_opened(void)239 monitor_subsys_is_opened( void )
240 {
241           return monitor_subsys_opened;
242 }
243 
244 int
monitor_back_register_subsys(monitor_subsys_t * ms)245 monitor_back_register_subsys(
246           monitor_subsys_t    *ms )
247 {
248           int       i = 0;
249 
250           if ( monitor_subsys ) {
251                     for ( ; monitor_subsys[ i ] != NULL; i++ )
252                               /* just count'em */ ;
253           }
254 
255           monitor_subsys = ch_realloc( monitor_subsys,
256                               ( 2 + i ) * sizeof( monitor_subsys_t * ) );
257 
258           if ( monitor_subsys == NULL ) {
259                     return -1;
260           }
261 
262           monitor_subsys[ i ] = ms;
263           monitor_subsys[ i + 1 ] = NULL;
264 
265           /* if a subsystem is registered __AFTER__ subsystem
266            * initialization (depending on the sequence the databases
267            * are listed in slapd.conf), init it */
268           if ( monitor_subsys_is_opened() ) {
269 
270                     /* FIXME: this should only be possible
271                      * if be_monitor is already initialized */
272                     assert( be_monitor != NULL );
273 
274                     if ( ms->mss_open && ( *ms->mss_open )( be_monitor, ms ) ) {
275                               return -1;
276                     }
277 
278                     ms->mss_flags |= MONITOR_F_OPENED;
279           }
280 
281           return 0;
282 }
283 
284 enum {
285           LIMBO_ENTRY,
286           LIMBO_ENTRY_PARENT,
287           LIMBO_ATTRS,
288           LIMBO_CB,
289           LIMBO_BACKEND,
290           LIMBO_DATABASE,
291           LIMBO_OVERLAY_INFO,
292           LIMBO_OVERLAY,
293           LIMBO_SUBSYS,
294 
295           LIMBO_LAST
296 };
297 
298 typedef struct entry_limbo_t {
299           int                           el_type;
300           BackendInfo                   *el_bi;
301           BackendDB           *el_be;
302           slap_overinst                 *el_on;
303           Entry                         *el_e;
304           Attribute           *el_a;
305           struct berval                 *el_ndn;
306           struct berval                 el_nbase;
307           int                           el_scope;
308           struct berval                 el_filter;
309           monitor_callback_t  *el_cb;
310           monitor_subsys_t    *el_mss;
311           unsigned long                 el_flags;
312           struct entry_limbo_t          *el_next;
313 } entry_limbo_t;
314 
315 int
monitor_back_is_configured(void)316 monitor_back_is_configured( void )
317 {
318           return be_monitor != NULL;
319 }
320 
321 int
monitor_back_register_subsys_late(monitor_subsys_t * ms)322 monitor_back_register_subsys_late(
323           monitor_subsys_t    *ms )
324 {
325           entry_limbo_t       **elpp, el = { 0 };
326           monitor_info_t      *mi;
327 
328           if ( be_monitor == NULL ) {
329                     Debug( LDAP_DEBUG_ANY,
330                               "monitor_back_register_subsys_late: "
331                               "monitor database not configured.\n" );
332                     return -1;
333           }
334 
335           /* everything is ready, can register already */
336           if ( monitor_subsys_is_opened() ) {
337                     return monitor_back_register_subsys( ms );
338           }
339 
340           mi = ( monitor_info_t * )be_monitor->be_private;
341 
342 
343           el.el_type = LIMBO_SUBSYS;
344 
345           el.el_mss = ms;
346 
347           for ( elpp = &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 
354           el.el_next = NULL;
355           **elpp = el;
356 
357           return 0;
358 }
359 
360 int
monitor_back_register_backend(BackendInfo * bi)361 monitor_back_register_backend(
362           BackendInfo                   *bi )
363 {
364           return -1;
365 }
366 
367 int
monitor_back_register_overlay_info(slap_overinst * on)368 monitor_back_register_overlay_info(
369           slap_overinst                 *on )
370 {
371           return -1;
372 }
373 
374 int
monitor_back_register_backend_limbo(BackendInfo * bi)375 monitor_back_register_backend_limbo(
376           BackendInfo                   *bi )
377 {
378           return -1;
379 }
380 
381 int
monitor_back_register_database_limbo(BackendDB * be,struct berval * ndn_out)382 monitor_back_register_database_limbo(
383           BackendDB           *be,
384           struct berval                 *ndn_out )
385 {
386           entry_limbo_t       **elpp, el = { 0 };
387           monitor_info_t      *mi;
388 
389           if ( be_monitor == NULL ) {
390                     Debug( LDAP_DEBUG_ANY,
391                               "monitor_back_register_database_limbo: "
392                               "monitor database not configured.\n" );
393                     return -1;
394           }
395 
396           mi = ( monitor_info_t * )be_monitor->be_private;
397 
398 
399           el.el_type = LIMBO_DATABASE;
400 
401           el.el_be = be->bd_self;
402           el.el_ndn = ndn_out;
403 
404           for ( elpp = &mi->mi_entry_limbo;
405                               *elpp;
406                               elpp = &(*elpp)->el_next )
407                     /* go to last */;
408 
409           *elpp = (entry_limbo_t *)ch_malloc( sizeof( entry_limbo_t ) );
410 
411           el.el_next = NULL;
412           **elpp = el;
413 
414           return 0;
415 }
416 
417 int
monitor_back_register_overlay_info_limbo(slap_overinst * on)418 monitor_back_register_overlay_info_limbo(
419           slap_overinst                 *on )
420 {
421           return -1;
422 }
423 
424 int
monitor_back_register_overlay_limbo(BackendDB * be,struct slap_overinst * on,struct berval * ndn_out)425 monitor_back_register_overlay_limbo(
426           BackendDB           *be,
427           struct slap_overinst          *on,
428           struct berval                 *ndn_out )
429 {
430           entry_limbo_t       **elpp, el = { 0 };
431           monitor_info_t      *mi;
432 
433           if ( be_monitor == NULL ) {
434                     Debug( LDAP_DEBUG_ANY,
435                               "monitor_back_register_overlay_limbo: "
436                               "monitor database not configured.\n" );
437                     return -1;
438           }
439 
440           mi = ( monitor_info_t * )be_monitor->be_private;
441 
442 
443           el.el_type = LIMBO_OVERLAY;
444 
445           el.el_be = be->bd_self;
446           el.el_on = on;
447           el.el_ndn = ndn_out;
448 
449           for ( elpp = &mi->mi_entry_limbo;
450                               *elpp;
451                               elpp = &(*elpp)->el_next )
452                     /* go to last */;
453 
454           *elpp = (entry_limbo_t *)ch_malloc( sizeof( entry_limbo_t ) );
455 
456           el.el_next = NULL;
457           **elpp = el;
458 
459           return 0;
460 }
461 
462 int
monitor_back_register_entry(Entry * e,monitor_callback_t * cb,monitor_subsys_t * mss,unsigned long flags)463 monitor_back_register_entry(
464           Entry                         *e,
465           monitor_callback_t  *cb,
466           monitor_subsys_t    *mss,
467           unsigned long                 flags )
468 {
469           monitor_info_t      *mi;
470           int rc = 0;
471 
472           if ( be_monitor == NULL ) {
473                     Debug( LDAP_DEBUG_ANY,
474                               "monitor_back_register_entry(\"%s\"): "
475                               "monitor database not configured.\n",
476                               e->e_name.bv_val );
477                     return -1;
478           }
479 
480           mi = ( monitor_info_t * )be_monitor->be_private;
481 
482           assert( mi != NULL );
483           assert( e != NULL );
484           assert( e->e_private == NULL );
485 
486           if ( monitor_subsys_is_opened() ) {
487                     Entry               *e_parent = NULL,
488                                         *e_new = NULL,
489                                         **ep = NULL;
490                     struct berval       pdn = BER_BVNULL;
491                     monitor_entry_t *mp = NULL,
492                                         *mp_parent = NULL;
493 
494                     if ( monitor_cache_get( mi, &e->e_nname, &e_parent ) == 0 ) {
495                               /* entry exists */
496                               Debug( LDAP_DEBUG_ANY,
497                                         "monitor_back_register_entry(\"%s\"): "
498                                         "entry exists\n",
499                                         e->e_name.bv_val );
500                               monitor_cache_release( mi, e_parent );
501                               return -1;
502                     }
503 
504                     dnParent( &e->e_nname, &pdn );
505                     if ( monitor_cache_get( mi, &pdn, &e_parent ) != 0 ) {
506                               /* parent does not exist */
507                               Debug( LDAP_DEBUG_ANY,
508                                         "monitor_back_register_entry(\"%s\"): "
509                                         "parent \"%s\" not found\n",
510                                         e->e_name.bv_val, pdn.bv_val );
511                               return -1;
512                     }
513 
514                     assert( e_parent->e_private != NULL );
515                     mp_parent = ( monitor_entry_t * )e_parent->e_private;
516 
517                     if ( mp_parent->mp_flags & MONITOR_F_VOLATILE ) {
518                               /* entry is volatile; cannot append children */
519                               Debug( LDAP_DEBUG_ANY,
520                                         "monitor_back_register_entry(\"%s\"): "
521                                         "parent \"%s\" is volatile\n",
522                                         e->e_name.bv_val, e_parent->e_name.bv_val );
523                               rc = -1;
524                               goto done;
525                     }
526 
527                     mp = monitor_entrypriv_create();
528                     if ( mp == NULL ) {
529                               Debug( LDAP_DEBUG_ANY,
530                                         "monitor_back_register_entry(\"%s\"): "
531                                         "monitor_entrypriv_create() failed\n",
532                                         e->e_name.bv_val );
533                               rc = -1;
534                               goto done;
535                     }
536 
537                     e_new = entry_dup( e );
538                     if ( e_new == NULL ) {
539                               Debug( LDAP_DEBUG_ANY,
540                                         "monitor_back_register_entry(\"%s\"): "
541                                         "entry_dup() failed\n",
542                                         e->e_name.bv_val );
543                               rc = -1;
544                               goto done;
545                     }
546 
547                     e_new->e_private = ( void * )mp;
548                     if ( mss != NULL ) {
549                               mp->mp_info = mss;
550                               mp->mp_flags = flags;
551 
552                     } else {
553                               mp->mp_info = mp_parent->mp_info;
554                               mp->mp_flags = mp_parent->mp_flags | MONITOR_F_SUB;
555                     }
556                     mp->mp_cb = cb;
557 
558                     ep = &mp_parent->mp_children;
559                     for ( ; *ep; ) {
560                               mp_parent = ( monitor_entry_t * )(*ep)->e_private;
561                               ep = &mp_parent->mp_next;
562                     }
563                     *ep = e_new;
564 
565                     if ( monitor_cache_add( mi, e_new ) ) {
566                               Debug( LDAP_DEBUG_ANY,
567                                         "monitor_back_register_entry(\"%s\"): "
568                                         "unable to add entry\n",
569                                         e->e_name.bv_val );
570                               rc = -1;
571                               goto done;
572                     }
573 
574 done:;
575                     if ( rc ) {
576                               if ( mp ) {
577                                         ch_free( mp );
578                               }
579                               if ( e_new ) {
580                                         e_new->e_private = NULL;
581                                         entry_free( e_new );
582                               }
583                     }
584 
585                     if ( e_parent ) {
586                               monitor_cache_release( mi, e_parent );
587                     }
588 
589           } else {
590                     entry_limbo_t       **elpp, el = { 0 };
591 
592                     el.el_type = LIMBO_ENTRY;
593 
594                     el.el_e = entry_dup( e );
595                     if ( el.el_e == NULL ) {
596                               Debug( LDAP_DEBUG_ANY,
597                                         "monitor_back_register_entry(\"%s\"): "
598                                         "entry_dup() failed\n",
599                                         e->e_name.bv_val );
600                               return -1;
601                     }
602 
603                     el.el_cb = cb;
604                     el.el_mss = mss;
605                     el.el_flags = flags;
606 
607                     for ( elpp = &mi->mi_entry_limbo;
608                                         *elpp;
609                                         elpp = &(*elpp)->el_next )
610                               /* go to last */;
611 
612                     *elpp = (entry_limbo_t *)ch_malloc( sizeof( entry_limbo_t ) );
613                     if ( *elpp == NULL ) {
614                               el.el_e->e_private = NULL;
615                               entry_free( el.el_e );
616                               return -1;
617                     }
618 
619                     el.el_next = NULL;
620                     **elpp = el;
621           }
622 
623           return rc;
624 }
625 
626 int
monitor_back_register_entry_parent(Entry * e,monitor_callback_t * cb,monitor_subsys_t * mss,unsigned long flags,struct berval * nbase,int scope,struct berval * filter)627 monitor_back_register_entry_parent(
628           Entry                         *e,
629           monitor_callback_t  *cb,
630           monitor_subsys_t    *mss,
631           unsigned long                 flags,
632           struct berval                 *nbase,
633           int                           scope,
634           struct berval                 *filter )
635 {
636           monitor_info_t      *mi;
637           struct berval       ndn = BER_BVNULL;
638 
639           if ( be_monitor == NULL ) {
640                     Debug( LDAP_DEBUG_ANY,
641                               "monitor_back_register_entry_parent(base=\"%s\" scope=%s filter=\"%s\"): "
642                               "monitor database not configured.\n",
643                               BER_BVISNULL( nbase ) ? "" : nbase->bv_val,
644                               ldap_pvt_scope2str( scope ),
645                               BER_BVISNULL( filter ) ? "" : filter->bv_val );
646                     return -1;
647           }
648 
649           mi = ( monitor_info_t * )be_monitor->be_private;
650 
651           assert( mi != NULL );
652           assert( e != NULL );
653           assert( e->e_private == NULL );
654 
655           if ( BER_BVISNULL( filter ) ) {
656                     /* need a filter */
657                     Debug( LDAP_DEBUG_ANY,
658                               "monitor_back_register_entry_parent(\"\"): "
659                               "need a valid filter\n" );
660                     return -1;
661           }
662 
663           if ( monitor_subsys_is_opened() ) {
664                     Entry               *e_parent = NULL,
665                                         *e_new = NULL,
666                                         **ep = NULL;
667                     struct berval       e_name = BER_BVNULL,
668                                         e_nname = BER_BVNULL;
669                     monitor_entry_t *mp = NULL,
670                                         *mp_parent = NULL;
671                     int                 rc = 0;
672 
673                     if ( monitor_search2ndn( nbase, scope, filter, &ndn ) ) {
674                               /* entry does not exist */
675                               Debug( LDAP_DEBUG_ANY,
676                                         "monitor_back_register_entry_parent(\"\"): "
677                                         "base=\"%s\" scope=%s filter=\"%s\": "
678                                         "unable to find entry\n",
679                                         nbase->bv_val ? nbase->bv_val : "\"\"",
680                                         ldap_pvt_scope2str( scope ),
681                                         filter->bv_val );
682                               return -1;
683                     }
684 
685                     if ( monitor_cache_get( mi, &ndn, &e_parent ) != 0 ) {
686                               /* entry does not exist */
687                               Debug( LDAP_DEBUG_ANY,
688                                         "monitor_back_register_entry_parent(\"%s\"): "
689                                         "parent entry does not exist\n",
690                                         ndn.bv_val );
691                               rc = -1;
692                               goto done;
693                     }
694 
695                     assert( e_parent->e_private != NULL );
696                     mp_parent = ( monitor_entry_t * )e_parent->e_private;
697 
698                     if ( mp_parent->mp_flags & MONITOR_F_VOLATILE ) {
699                               /* entry is volatile; cannot append callback */
700                               Debug( LDAP_DEBUG_ANY,
701                                         "monitor_back_register_entry_parent(\"%s\"): "
702                                         "entry is volatile\n",
703                                         e_parent->e_name.bv_val );
704                               rc = -1;
705                               goto done;
706                     }
707 
708                     build_new_dn( &e_name, &e_parent->e_name, &e->e_name, NULL );
709                     build_new_dn( &e_nname, &e_parent->e_nname, &e->e_nname, NULL );
710 
711                     if ( monitor_cache_get( mi, &e_nname, &e_new ) == 0 ) {
712                               /* entry already exists */
713                               Debug( LDAP_DEBUG_ANY,
714                                         "monitor_back_register_entry_parent(\"%s\"): "
715                                         "entry already exists\n",
716                                         e_name.bv_val );
717                               monitor_cache_release( mi, e_new );
718                               e_new = NULL;
719                               rc = -1;
720                               goto done;
721                     }
722 
723                     mp = monitor_entrypriv_create();
724                     if ( mp == NULL ) {
725                               Debug( LDAP_DEBUG_ANY,
726                                         "monitor_back_register_entry_parent(\"%s\"): "
727                                         "monitor_entrypriv_create() failed\n",
728                                         e->e_name.bv_val );
729                               rc = -1;
730                               goto done;
731                     }
732 
733                     e_new = entry_dup( e );
734                     if ( e_new == NULL ) {
735                               Debug( LDAP_DEBUG_ANY,
736                                         "monitor_back_register_entry(\"%s\"): "
737                                         "entry_dup() failed\n",
738                                         e->e_name.bv_val );
739                               rc = -1;
740                               goto done;
741                     }
742                     ch_free( e_new->e_name.bv_val );
743                     ch_free( e_new->e_nname.bv_val );
744                     e_new->e_name = e_name;
745                     e_new->e_nname = e_nname;
746 
747                     e_new->e_private = ( void * )mp;
748                     if ( mss != NULL ) {
749                               mp->mp_info = mss;
750                               mp->mp_flags = flags;
751 
752                     } else {
753                               mp->mp_info = mp_parent->mp_info;
754                               mp->mp_flags = mp_parent->mp_flags | MONITOR_F_SUB;
755                     }
756                     mp->mp_cb = cb;
757 
758                     ep = &mp_parent->mp_children;
759                     for ( ; *ep; ) {
760                               mp_parent = ( monitor_entry_t * )(*ep)->e_private;
761                               ep = &mp_parent->mp_next;
762                     }
763                     *ep = e_new;
764 
765                     if ( monitor_cache_add( mi, e_new ) ) {
766                               Debug( LDAP_DEBUG_ANY,
767                                         "monitor_back_register_entry(\"%s\"): "
768                                         "unable to add entry\n",
769                                         e->e_name.bv_val );
770                               rc = -1;
771                               goto done;
772                     }
773 
774 done:;
775                     if ( !BER_BVISNULL( &ndn ) ) {
776                               ch_free( ndn.bv_val );
777                     }
778 
779                     if ( rc ) {
780                               if ( mp ) {
781                                         ch_free( mp );
782                               }
783                               if ( e_new ) {
784                                         e_new->e_private = NULL;
785                                         entry_free( e_new );
786                               }
787                     }
788 
789                     if ( e_parent ) {
790                               monitor_cache_release( mi, e_parent );
791                     }
792 
793           } else {
794                     entry_limbo_t       **elpp = NULL, el = { 0 };
795 
796                     el.el_type = LIMBO_ENTRY_PARENT;
797 
798                     el.el_e = entry_dup( e );
799                     if ( el.el_e == NULL ) {
800                               Debug( LDAP_DEBUG_ANY,
801                                         "monitor_back_register_entry(\"%s\"): "
802                                         "entry_dup() failed\n",
803                                         e->e_name.bv_val );
804                               goto done_limbo;
805                     }
806 
807                     if ( !BER_BVISNULL( nbase ) ) {
808                               ber_dupbv( &el.el_nbase, nbase );
809                     }
810 
811                     el.el_scope = scope;
812                     if ( !BER_BVISNULL( filter ) ) {
813                               ber_dupbv( &el.el_filter, filter  );
814                     }
815 
816                     el.el_cb = cb;
817                     el.el_mss = mss;
818                     el.el_flags = flags;
819 
820                     for ( elpp = &mi->mi_entry_limbo;
821                                         *elpp;
822                                         elpp = &(*elpp)->el_next )
823                               /* go to last */;
824 
825                     *elpp = (entry_limbo_t *)ch_malloc( sizeof( entry_limbo_t ) );
826                     if ( *elpp == NULL ) {
827                               goto done_limbo;
828                     }
829 
830 done_limbo:;
831                     if ( *elpp != NULL ) {
832                               el.el_next = NULL;
833                               **elpp = el;
834 
835                     } else {
836                               if ( !BER_BVISNULL( &el.el_filter ) ) {
837                                         ch_free( el.el_filter.bv_val );
838                               }
839                               if ( !BER_BVISNULL( &el.el_nbase ) ) {
840                                         ch_free( el.el_nbase.bv_val );
841                               }
842                               entry_free( el.el_e );
843                               return -1;
844                     }
845           }
846 
847           return 0;
848 }
849 
850 static int
monitor_search2ndn_cb(Operation * op,SlapReply * rs)851 monitor_search2ndn_cb( Operation *op, SlapReply *rs )
852 {
853           if ( rs->sr_type == REP_SEARCH ) {
854                     struct berval       *ndn = op->o_callback->sc_private;
855 
856                     if ( !BER_BVISNULL( ndn ) ) {
857                               rs->sr_err = LDAP_SIZELIMIT_EXCEEDED;
858                               ch_free( ndn->bv_val );
859                               BER_BVZERO( ndn );
860                               return rs->sr_err;
861                     }
862 
863                     ber_dupbv( ndn, &rs->sr_entry->e_nname );
864           }
865 
866           return 0;
867 }
868 
869 int
monitor_search2ndn(struct berval * nbase,int scope,struct berval * filter,struct berval * ndn)870 monitor_search2ndn(
871           struct berval       *nbase,
872           int                 scope,
873           struct berval       *filter,
874           struct berval       *ndn )
875 {
876           Connection          conn = { 0 };
877           OperationBuffer     opbuf;
878           Operation *op;
879           void      *thrctx;
880           SlapReply rs = { REP_RESULT };
881           slap_callback       cb = { NULL, monitor_search2ndn_cb, NULL, NULL };
882           int                 rc;
883 
884           BER_BVZERO( ndn );
885 
886           if ( be_monitor == NULL ) {
887                     return -1;
888           }
889 
890           thrctx = ldap_pvt_thread_pool_context();
891           connection_fake_init2( &conn, &opbuf, thrctx, 0 );
892           op = &opbuf.ob_op;
893 
894           op->o_tag = LDAP_REQ_SEARCH;
895 
896           /* use global malloc for now */
897           if ( op->o_tmpmemctx ) {
898                     op->o_tmpmemctx = NULL;
899           }
900           op->o_tmpmfuncs = &ch_mfuncs;
901 
902           op->o_bd = be_monitor;
903           if ( nbase == NULL || BER_BVISNULL( nbase ) ) {
904                     ber_dupbv_x( &op->o_req_dn, &op->o_bd->be_suffix[ 0 ],
905                                         op->o_tmpmemctx );
906                     ber_dupbv_x( &op->o_req_ndn, &op->o_bd->be_nsuffix[ 0 ],
907                                         op->o_tmpmemctx );
908 
909           } else {
910                     if ( dnPrettyNormal( NULL, nbase, &op->o_req_dn, &op->o_req_ndn,
911                                                   op->o_tmpmemctx ) ) {
912                               return -1;
913                     }
914           }
915 
916           op->o_callback = &cb;
917           cb.sc_private = (void *)ndn;
918 
919           op->ors_scope = scope;
920           op->ors_filter = str2filter_x( op, filter->bv_val );
921           if ( op->ors_filter == NULL ) {
922                     rc = LDAP_OTHER;
923                     goto cleanup;
924           }
925           ber_dupbv_x( &op->ors_filterstr, filter, op->o_tmpmemctx );
926           op->ors_attrs = slap_anlist_no_attrs;
927           op->ors_attrsonly = 0;
928           op->ors_tlimit = SLAP_NO_LIMIT;
929           op->ors_slimit = 1;
930           op->ors_limit = NULL;
931           op->ors_deref = LDAP_DEREF_NEVER;
932 
933           op->o_nocaching = 1;
934           op->o_managedsait = SLAP_CONTROL_NONCRITICAL;
935 
936           op->o_dn = be_monitor->be_rootdn;
937           op->o_ndn = be_monitor->be_rootndn;
938 
939           rc = op->o_bd->be_search( op, &rs );
940 
941 cleanup:;
942           if ( op->ors_filter != NULL ) {
943                     filter_free_x( op, op->ors_filter, 1 );
944           }
945           if ( !BER_BVISNULL( &op->ors_filterstr ) ) {
946                     op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
947           }
948           if ( !BER_BVISNULL( &op->o_req_dn ) ) {
949                     op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx );
950           }
951           if ( !BER_BVISNULL( &op->o_req_ndn ) ) {
952                     op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );
953           }
954 
955           if ( rc != 0 ) {
956                     return rc;
957           }
958 
959           switch ( rs.sr_err ) {
960           case LDAP_SUCCESS:
961                     if ( BER_BVISNULL( ndn ) ) {
962                               rc = -1;
963                     }
964                     break;
965 
966           case LDAP_SIZELIMIT_EXCEEDED:
967           default:
968                     if ( !BER_BVISNULL( ndn ) ) {
969                               ber_memfree( ndn->bv_val );
970                               BER_BVZERO( ndn );
971                     }
972                     rc = -1;
973                     break;
974           }
975 
976           return rc;
977 }
978 
979 int
monitor_back_register_entry_attrs(struct berval * ndn_in,Attribute * a,monitor_callback_t * cb,struct berval * nbase,int scope,struct berval * filter)980 monitor_back_register_entry_attrs(
981           struct berval                 *ndn_in,
982           Attribute           *a,
983           monitor_callback_t  *cb,
984           struct berval                 *nbase,
985           int                           scope,
986           struct berval                 *filter )
987 {
988           monitor_info_t      *mi;
989           struct berval       ndn = BER_BVNULL;
990           char                *fname = ( a == NULL ? "callback" : "attrs" );
991           struct berval       empty_bv = BER_BVC("");
992 
993           if ( nbase == NULL ) nbase = &empty_bv;
994           if ( filter == NULL ) filter = &empty_bv;
995 
996           if ( be_monitor == NULL ) {
997                     Debug(LDAP_DEBUG_ANY,
998                           "monitor_back_register_entry_%s(base=\"%s\" scope=%s filter=\"%s\"): " "monitor database not configured.\n\n",
999                           fname, BER_BVISNULL(nbase) ? "" : nbase->bv_val,
1000                           ldap_pvt_scope2str(scope),
1001                           BER_BVISNULL(filter) ? "" : filter->bv_val );
1002 
1003                     return -1;
1004           }
1005 
1006           mi = ( monitor_info_t * )be_monitor->be_private;
1007 
1008           assert( mi != NULL );
1009 
1010           if ( ndn_in != NULL ) {
1011                     ndn = *ndn_in;
1012           }
1013 
1014           if ( a == NULL && cb == NULL ) {
1015                     /* nothing to do */
1016                     return -1;
1017           }
1018 
1019           if ( ( ndn_in == NULL || BER_BVISNULL( &ndn ) )
1020                               && BER_BVISNULL( filter ) )
1021           {
1022                     /* need a filter */
1023                     Debug( LDAP_DEBUG_ANY,
1024                               "monitor_back_register_entry_%s(\"\"): "
1025                               "need a valid filter\n",
1026                               fname );
1027                     return -1;
1028           }
1029 
1030           if ( monitor_subsys_is_opened() ) {
1031                     Entry                         *e = NULL;
1032                     Attribute           **atp = NULL;
1033                     monitor_entry_t     *mp = NULL;
1034                     monitor_callback_t  **mcp = NULL;
1035                     int                           rc = 0;
1036                     int                           freeit = 0;
1037 
1038                     if ( BER_BVISNULL( &ndn ) ) {
1039                               if ( monitor_search2ndn( nbase, scope, filter, &ndn ) ) {
1040                                         Debug(LDAP_DEBUG_ANY,
1041                                               "monitor_back_register_entry_%s(\"\"): " "base=\"%s\" scope=%s filter=\"%s\": " "unable to find entry\n\n",
1042                                               fname,
1043                                               nbase->bv_val ? nbase->bv_val : "\"\"",
1044                                               ldap_pvt_scope2str(scope),
1045                                               filter->bv_val );
1046                                         return -1;
1047                               }
1048 
1049                               freeit = 1;
1050                     }
1051 
1052                     if ( monitor_cache_get( mi, &ndn, &e ) != 0 ) {
1053                               /* entry does not exist */
1054                               Debug( LDAP_DEBUG_ANY,
1055                                         "monitor_back_register_entry_%s(\"%s\"): "
1056                                         "entry does not exist\n",
1057                                         fname, ndn.bv_val );
1058                               rc = -1;
1059                               goto done;
1060                     }
1061 
1062                     assert( e->e_private != NULL );
1063                     mp = ( monitor_entry_t * )e->e_private;
1064 
1065                     if ( mp->mp_flags & MONITOR_F_VOLATILE ) {
1066                               /* entry is volatile; cannot append callback */
1067                               Debug( LDAP_DEBUG_ANY,
1068                                         "monitor_back_register_entry_%s(\"%s\"): "
1069                                         "entry is volatile\n",
1070                                         fname, e->e_name.bv_val );
1071                               rc = -1;
1072                               goto done;
1073                     }
1074 
1075                     if ( a ) {
1076                               for ( atp = &e->e_attrs; *atp; atp = &(*atp)->a_next )
1077                                         /* just get to last */ ;
1078 
1079                               for ( ; a != NULL; a = a->a_next ) {
1080                                         assert( a->a_desc != NULL );
1081                                         assert( a->a_vals != NULL );
1082 
1083                                         if ( attr_find( e->e_attrs, a->a_desc ) ) {
1084                                                   attr_merge( e, a->a_desc, a->a_vals,
1085                                                             a->a_nvals == a->a_vals ? NULL : a->a_nvals );
1086 
1087                                         } else {
1088                                                   *atp = attr_dup( a );
1089                                                   if ( *atp == NULL ) {
1090                                                             Debug( LDAP_DEBUG_ANY,
1091                                                                       "monitor_back_register_entry_%s(\"%s\"): "
1092                                                                       "attr_dup() failed\n",
1093                                                                       fname, e->e_name.bv_val );
1094                                                             rc = -1;
1095                                                             goto done;
1096                                                   }
1097                                                   atp = &(*atp)->a_next;
1098                                         }
1099                               }
1100                     }
1101 
1102                     if ( cb ) {
1103                               for ( mcp = &mp->mp_cb; *mcp; mcp = &(*mcp)->mc_next )
1104                                         /* go to tail */ ;
1105 
1106                               /* NOTE: we do not clear cb->mc_next, so this function
1107                                * can be used to append a list of callbacks */
1108                               (*mcp) = cb;
1109                     }
1110 
1111 done:;
1112                     if ( rc ) {
1113                               if ( atp && *atp ) {
1114                                         attrs_free( *atp );
1115                                         *atp = NULL;
1116                               }
1117                     }
1118 
1119                     if ( freeit ) {
1120                               ber_memfree( ndn.bv_val );
1121                     }
1122 
1123                     if ( e ) {
1124                               monitor_cache_release( mi, e );
1125                     }
1126 
1127           } else {
1128                     entry_limbo_t       **elpp, el = { 0 };
1129 
1130                     el.el_type = LIMBO_ATTRS;
1131                     el.el_ndn = ndn_in;
1132                     if ( !BER_BVISNULL( nbase ) ) {
1133                               ber_dupbv( &el.el_nbase, nbase);
1134                     }
1135                     el.el_scope = scope;
1136                     if ( !BER_BVISNULL( filter ) ) {
1137                               ber_dupbv( &el.el_filter, filter  );
1138                     }
1139 
1140                     el.el_a = attrs_dup( a );
1141                     el.el_cb = cb;
1142 
1143                     for ( elpp = &mi->mi_entry_limbo;
1144                                         *elpp;
1145                                         elpp = &(*elpp)->el_next )
1146                               /* go to last */;
1147 
1148                     *elpp = (entry_limbo_t *)ch_malloc( sizeof( entry_limbo_t ) );
1149                     if ( *elpp == NULL ) {
1150                               if ( !BER_BVISNULL( &el.el_filter ) ) {
1151                                         ch_free( el.el_filter.bv_val );
1152                               }
1153                               if ( el.el_a != NULL ) {
1154                                         attrs_free( el.el_a );
1155                               }
1156                               if ( !BER_BVISNULL( &el.el_nbase ) ) {
1157                                         ch_free( &el.el_nbase.bv_val );
1158                               }
1159                               return -1;
1160                     }
1161 
1162                     el.el_next = NULL;
1163                     **elpp = el;
1164           }
1165 
1166           return 0;
1167 }
1168 
1169 int
monitor_back_register_entry_callback(struct berval * ndn,monitor_callback_t * cb,struct berval * nbase,int scope,struct berval * filter)1170 monitor_back_register_entry_callback(
1171           struct berval                 *ndn,
1172           monitor_callback_t  *cb,
1173           struct berval                 *nbase,
1174           int                           scope,
1175           struct berval                 *filter )
1176 {
1177           return monitor_back_register_entry_attrs( ndn, NULL, cb,
1178                               nbase, scope, filter );
1179 }
1180 
1181 /*
1182  * TODO: add corresponding calls to remove installed callbacks, entries
1183  * and so, in case the entity that installed them is removed (e.g. a
1184  * database, via back-config)
1185  */
1186 int
monitor_back_unregister_entry(struct berval * ndn)1187 monitor_back_unregister_entry(
1188           struct berval       *ndn )
1189 {
1190           monitor_info_t      *mi;
1191 
1192           if ( be_monitor == NULL ) {
1193                     Debug( LDAP_DEBUG_ANY,
1194                               "monitor_back_unregister_entry(\"%s\"): "
1195                               "monitor database not configured.\n",
1196                               ndn->bv_val );
1197 
1198                     return -1;
1199           }
1200 
1201           /* entry will be regularly freed, and resources released
1202            * according to callbacks */
1203           if ( slapd_shutdown ) {
1204                     return 0;
1205           }
1206 
1207           mi = ( monitor_info_t * )be_monitor->be_private;
1208 
1209           assert( mi != NULL );
1210 
1211           if ( monitor_subsys_is_opened() ) {
1212                     Entry                         *e = NULL;
1213                     monitor_entry_t     *mp = NULL;
1214                     monitor_callback_t  *cb = NULL;
1215 
1216                     if ( monitor_cache_remove( mi, ndn, &e ) != 0 ) {
1217                               /* entry does not exist */
1218                               Debug( LDAP_DEBUG_ANY,
1219                                         "monitor_back_unregister_entry(\"%s\"): "
1220                                         "entry removal failed.\n",
1221                                         ndn->bv_val );
1222                               return -1;
1223                     }
1224 
1225                     mp = (monitor_entry_t *)e->e_private;
1226                     assert( mp != NULL );
1227 
1228                     for ( cb = mp->mp_cb; cb != NULL; ) {
1229                               monitor_callback_t  *next = cb->mc_next;
1230 
1231                               if ( cb->mc_free ) {
1232                                         (void)cb->mc_free( e, &cb->mc_private );
1233                               }
1234                               ch_free( cb );
1235 
1236                               cb = next;
1237                     }
1238 
1239                     ch_free( mp );
1240                     e->e_private = NULL;
1241                     entry_free( e );
1242 
1243           } else {
1244                     entry_limbo_t       **elpp;
1245 
1246                     for ( elpp = &mi->mi_entry_limbo;
1247                               *elpp;
1248                               elpp = &(*elpp)->el_next )
1249                     {
1250                               entry_limbo_t       *elp = *elpp;
1251 
1252                               if ( elp->el_type == LIMBO_ENTRY
1253                                         && dn_match( ndn, &elp->el_e->e_nname ) )
1254                               {
1255                                         monitor_callback_t  *cb, *next;
1256 
1257                                         for ( cb = elp->el_cb; cb; cb = next ) {
1258                                                   /* FIXME: call callbacks? */
1259                                                   next = cb->mc_next;
1260                                                   if ( cb->mc_dispose ) {
1261                                                             cb->mc_dispose( &cb->mc_private );
1262                                                   }
1263                                                   ch_free( cb );
1264                                         }
1265                                         assert( elp->el_e != NULL );
1266                                         elp->el_e->e_private = NULL;
1267                                         entry_free( elp->el_e );
1268                                         *elpp = elp->el_next;
1269                                         ch_free( elp );
1270                                         elpp = NULL;
1271                                         break;
1272                               }
1273                     }
1274 
1275                     if ( elpp != NULL ) {
1276                               /* not found!  where did it go? */
1277                               return 1;
1278                     }
1279           }
1280 
1281           return 0;
1282 }
1283 
1284 int
monitor_back_unregister_entry_parent(struct berval * nrdn,monitor_callback_t * target_cb,struct berval * nbase,int scope,struct berval * filter)1285 monitor_back_unregister_entry_parent(
1286           struct berval                 *nrdn,
1287           monitor_callback_t  *target_cb,
1288           struct berval                 *nbase,
1289           int                           scope,
1290           struct berval                 *filter )
1291 {
1292           monitor_info_t      *mi;
1293           struct berval       ndn = BER_BVNULL;
1294 
1295           if ( be_monitor == NULL ) {
1296                     Debug( LDAP_DEBUG_ANY,
1297                               "monitor_back_unregister_entry_parent(base=\"%s\" scope=%s filter=\"%s\"): "
1298                               "monitor database not configured.\n",
1299                               BER_BVISNULL( nbase ) ? "" : nbase->bv_val,
1300                               ldap_pvt_scope2str( scope ),
1301                               BER_BVISNULL( filter ) ? "" : filter->bv_val );
1302 
1303                     return -1;
1304           }
1305 
1306           /* entry will be regularly freed, and resources released
1307            * according to callbacks */
1308           if ( slapd_shutdown ) {
1309                     return 0;
1310           }
1311 
1312           mi = ( monitor_info_t * )be_monitor->be_private;
1313 
1314           assert( mi != NULL );
1315 
1316           if ( ( nrdn == NULL || BER_BVISNULL( nrdn ) )
1317                               && BER_BVISNULL( filter ) )
1318           {
1319                     /* need a filter */
1320                     Debug( LDAP_DEBUG_ANY,
1321                               "monitor_back_unregister_entry_parent(\"\"): "
1322                               "need a valid filter\n" );
1323                     return -1;
1324           }
1325 
1326           if ( monitor_subsys_is_opened() ) {
1327                     Entry                         *e = NULL;
1328                     monitor_entry_t     *mp = NULL;
1329 
1330                     if ( monitor_search2ndn( nbase, scope, filter, &ndn ) ) {
1331                               /* entry does not exist */
1332                               Debug( LDAP_DEBUG_ANY,
1333                                         "monitor_back_unregister_entry_parent(\"\"): "
1334                                         "base=\"%s\" scope=%s filter=\"%s\": "
1335                                         "unable to find entry\n",
1336                                         nbase->bv_val ? nbase->bv_val : "\"\"",
1337                                         ldap_pvt_scope2str( scope ),
1338                                         filter->bv_val );
1339                               return -1;
1340                     }
1341 
1342                     if ( monitor_cache_remove( mi, &ndn, &e ) != 0 ) {
1343                               /* entry does not exist */
1344                               Debug( LDAP_DEBUG_ANY,
1345                                         "monitor_back_unregister_entry(\"%s\"): "
1346                                         "entry removal failed.\n",
1347                                         ndn.bv_val );
1348                               ber_memfree( ndn.bv_val );
1349                               return -1;
1350                     }
1351                     ber_memfree( ndn.bv_val );
1352 
1353                     mp = (monitor_entry_t *)e->e_private;
1354                     assert( mp != NULL );
1355 
1356                     if ( target_cb != NULL ) {
1357                               monitor_callback_t  **cbp;
1358 
1359                               for ( cbp = &mp->mp_cb; *cbp != NULL; cbp = &(*cbp)->mc_next ) {
1360                                         if ( *cbp == target_cb ) {
1361                                                   if ( (*cbp)->mc_free ) {
1362                                                             (void)(*cbp)->mc_free( e, &(*cbp)->mc_private );
1363                                                   }
1364                                                   *cbp = (*cbp)->mc_next;
1365                                                   ch_free( target_cb );
1366                                                   break;
1367                                         }
1368                               }
1369                     }
1370 
1371 
1372                     ch_free( mp );
1373                     e->e_private = NULL;
1374                     entry_free( e );
1375 
1376           } else {
1377                     entry_limbo_t       **elpp;
1378 
1379                     for ( elpp = &mi->mi_entry_limbo;
1380                               *elpp;
1381                               elpp = &(*elpp)->el_next )
1382                     {
1383                               entry_limbo_t       *elp = *elpp;
1384 
1385                               if ( elp->el_type == LIMBO_ENTRY_PARENT
1386                                         && dn_match( nrdn, &elp->el_e->e_nname )
1387                                         && dn_match( nbase, &elp->el_nbase )
1388                                         && scope == elp->el_scope
1389                                         && bvmatch( filter, &elp->el_filter ) )
1390                               {
1391                                         monitor_callback_t  *cb, *next;
1392 
1393                                         for ( cb = elp->el_cb; cb; cb = next ) {
1394                                                   /* FIXME: call callbacks? */
1395                                                   next = cb->mc_next;
1396                                                   if ( cb->mc_dispose ) {
1397                                                             cb->mc_dispose( &cb->mc_private );
1398                                                   }
1399                                                   ch_free( cb );
1400                                         }
1401                                         assert( elp->el_e != NULL );
1402                                         elp->el_e->e_private = NULL;
1403                                         entry_free( elp->el_e );
1404                                         if ( !BER_BVISNULL( &elp->el_nbase ) ) {
1405                                                   ch_free( elp->el_nbase.bv_val );
1406                                         }
1407                                         if ( !BER_BVISNULL( &elp->el_filter ) ) {
1408                                                   ch_free( elp->el_filter.bv_val );
1409                                         }
1410                                         *elpp = elp->el_next;
1411                                         ch_free( elp );
1412                                         elpp = NULL;
1413                                         break;
1414                               }
1415                     }
1416 
1417                     if ( elpp != NULL ) {
1418                               /* not found!  where did it go? */
1419                               return 1;
1420                     }
1421           }
1422 
1423           return 0;
1424 }
1425 
1426 int
monitor_back_unregister_entry_attrs(struct berval * ndn_in,Attribute * target_a,monitor_callback_t * target_cb,struct berval * nbase,int scope,struct berval * filter)1427 monitor_back_unregister_entry_attrs(
1428           struct berval                 *ndn_in,
1429           Attribute           *target_a,
1430           monitor_callback_t  *target_cb,
1431           struct berval                 *nbase,
1432           int                           scope,
1433           struct berval                 *filter )
1434 {
1435           monitor_info_t      *mi;
1436           struct berval       ndn = BER_BVNULL;
1437           char                *fname = ( target_a == NULL ? "callback" : "attrs" );
1438 
1439           if ( be_monitor == NULL ) {
1440                     Debug(LDAP_DEBUG_ANY,
1441                           "monitor_back_unregister_entry_%s(base=\"%s\" scope=%s filter=\"%s\"): " "monitor database not configured.\n\n",
1442                           fname, BER_BVISNULL(nbase) ? "" : nbase->bv_val,
1443                           ldap_pvt_scope2str(scope),
1444                           BER_BVISNULL(filter) ? "" : filter->bv_val );
1445 
1446                     return -1;
1447           }
1448 
1449           /* entry will be regularly freed, and resources released
1450            * according to callbacks */
1451           if ( slapd_shutdown ) {
1452                     return 0;
1453           }
1454 
1455           mi = ( monitor_info_t * )be_monitor->be_private;
1456 
1457           assert( mi != NULL );
1458 
1459           if ( ndn_in != NULL ) {
1460                     ndn = *ndn_in;
1461           }
1462 
1463           if ( target_a == NULL && target_cb == NULL ) {
1464                     /* nothing to do */
1465                     return -1;
1466           }
1467 
1468           if ( ( ndn_in == NULL || BER_BVISNULL( &ndn ) )
1469                               && BER_BVISNULL( filter ) )
1470           {
1471                     /* need a filter */
1472                     Debug( LDAP_DEBUG_ANY,
1473                               "monitor_back_unregister_entry_%s(\"\"): "
1474                               "need a valid filter\n",
1475                               fname );
1476                     return -1;
1477           }
1478 
1479           if ( monitor_subsys_is_opened() ) {
1480                     Entry                         *e = NULL;
1481                     monitor_entry_t     *mp = NULL;
1482                     int                           freeit = 0;
1483 
1484                     if ( BER_BVISNULL( &ndn ) ) {
1485                               if ( monitor_search2ndn( nbase, scope, filter, &ndn ) ) {
1486                                         Debug(LDAP_DEBUG_ANY,
1487                                               "monitor_back_unregister_entry_%s(\"\"): " "base=\"%s\" scope=%d filter=\"%s\": " "unable to find entry\n\n",
1488                                               fname,
1489                                               nbase->bv_val ? nbase->bv_val : "\"\"",
1490                                               scope, filter->bv_val );
1491                                         return -1;
1492                               }
1493 
1494                               freeit = 1;
1495                     }
1496 
1497                     if ( monitor_cache_get( mi, &ndn, &e ) != 0 ) {
1498                               /* entry does not exist */
1499                               Debug( LDAP_DEBUG_ANY,
1500                                         "monitor_back_unregister_entry(\"%s\"): "
1501                                         "entry removal failed.\n",
1502                                         ndn.bv_val );
1503                               return -1;
1504                     }
1505 
1506                     mp = (monitor_entry_t *)e->e_private;
1507                     assert( mp != NULL );
1508 
1509                     if ( target_cb != NULL ) {
1510                               monitor_callback_t  **cbp;
1511 
1512                               for ( cbp = &mp->mp_cb; *cbp != NULL; cbp = &(*cbp)->mc_next ) {
1513                                         if ( *cbp == target_cb ) {
1514                                                   if ( (*cbp)->mc_free ) {
1515                                                             (void)(*cbp)->mc_free( e, &(*cbp)->mc_private );
1516                                                   }
1517                                                   *cbp = (*cbp)->mc_next;
1518                                                   ch_free( target_cb );
1519                                                   break;
1520                                         }
1521                               }
1522                     }
1523 
1524                     if ( target_a != NULL ) {
1525                               Attribute *a;
1526 
1527                               for ( a = target_a; a != NULL; a = a->a_next ) {
1528                                         Modification        mod = { 0 };
1529                                         const char          *text;
1530                                         char                textbuf[ SLAP_TEXT_BUFLEN ];
1531 
1532                                         mod.sm_op = LDAP_MOD_DELETE;
1533                                         mod.sm_desc = a->a_desc;
1534                                         mod.sm_values = a->a_vals;
1535                                         mod.sm_nvalues = a->a_nvals;
1536 
1537                                         (void)modify_delete_values( e, &mod, 1,
1538                                                   &text, textbuf, sizeof( textbuf ) );
1539                               }
1540                     }
1541 
1542                     if ( freeit ) {
1543                               ber_memfree( ndn.bv_val );
1544                     }
1545 
1546                     monitor_cache_release( mi, e );
1547 
1548           } else {
1549                     entry_limbo_t       **elpp;
1550 
1551                     for ( elpp = &mi->mi_entry_limbo;
1552                               *elpp;
1553                               elpp = &(*elpp)->el_next )
1554                     {
1555                               entry_limbo_t       *elp = *elpp;
1556 
1557                               if ( elp->el_type == LIMBO_ATTRS
1558                                         && dn_match( nbase, &elp->el_nbase )
1559                                         && scope == elp->el_scope
1560                                         && bvmatch( filter, &elp->el_filter ) )
1561                               {
1562                                         monitor_callback_t  *cb, *next;
1563 
1564                                         for ( cb = elp->el_cb; cb; cb = next ) {
1565                                                   /* FIXME: call callbacks? */
1566                                                   next = cb->mc_next;
1567                                                   if ( cb->mc_dispose ) {
1568                                                             cb->mc_dispose( &cb->mc_private );
1569                                                   }
1570                                                   ch_free( cb );
1571                                         }
1572                                         assert( elp->el_e == NULL );
1573                                         if ( elp->el_a != NULL ) {
1574                                                   attrs_free( elp->el_a );
1575                                         }
1576                                         if ( !BER_BVISNULL( &elp->el_nbase ) ) {
1577                                                   ch_free( elp->el_nbase.bv_val );
1578                                         }
1579                                         if ( !BER_BVISNULL( &elp->el_filter ) ) {
1580                                                   ch_free( elp->el_filter.bv_val );
1581                                         }
1582                                         *elpp = elp->el_next;
1583                                         ch_free( elp );
1584                                         elpp = NULL;
1585                                         break;
1586                               }
1587                     }
1588 
1589                     if ( elpp != NULL ) {
1590                               /* not found!  where did it go? */
1591                               return 1;
1592                     }
1593           }
1594 
1595           return 0;
1596 }
1597 
1598 int
monitor_back_unregister_entry_callback(struct berval * ndn,monitor_callback_t * cb,struct berval * nbase,int scope,struct berval * filter)1599 monitor_back_unregister_entry_callback(
1600           struct berval                 *ndn,
1601           monitor_callback_t  *cb,
1602           struct berval                 *nbase,
1603           int                           scope,
1604           struct berval                 *filter )
1605 {
1606           /* TODO: lookup entry (by ndn, if not NULL, and/or by callback);
1607            * unregister the callback; if a is not null, unregister the
1608            * given attrs.  In any case, call cb->cb_free */
1609           return monitor_back_unregister_entry_attrs( ndn,
1610                     NULL, cb, nbase, scope, filter );
1611 }
1612 
1613 monitor_subsys_t *
monitor_back_get_subsys(const char * name)1614 monitor_back_get_subsys( const char *name )
1615 {
1616           if ( monitor_subsys != NULL ) {
1617                     int       i;
1618 
1619                     for ( i = 0; monitor_subsys[ i ] != NULL; i++ ) {
1620                               if ( strcasecmp( monitor_subsys[ i ]->mss_name, name ) == 0 ) {
1621                                         return monitor_subsys[ i ];
1622                               }
1623                     }
1624           }
1625 
1626           return NULL;
1627 }
1628 
1629 monitor_subsys_t *
monitor_back_get_subsys_by_dn(struct berval * ndn,int sub)1630 monitor_back_get_subsys_by_dn(
1631           struct berval       *ndn,
1632           int                 sub )
1633 {
1634           if ( monitor_subsys != NULL ) {
1635                     int       i;
1636 
1637                     if ( sub ) {
1638                               for ( i = 0; monitor_subsys[ i ] != NULL; i++ ) {
1639                                         if ( dnIsSuffix( ndn, &monitor_subsys[ i ]->mss_ndn ) ) {
1640                                                   return monitor_subsys[ i ];
1641                                         }
1642                               }
1643 
1644                     } else {
1645                               for ( i = 0; monitor_subsys[ i ] != NULL; i++ ) {
1646                                         if ( dn_match( ndn, &monitor_subsys[ i ]->mss_ndn ) ) {
1647                                                   return monitor_subsys[ i ];
1648                                         }
1649                               }
1650                     }
1651           }
1652 
1653           return NULL;
1654 }
1655 
1656 int
monitor_back_initialize(BackendInfo * bi)1657 monitor_back_initialize(
1658           BackendInfo         *bi )
1659 {
1660           static char                   *controls[] = {
1661                     LDAP_CONTROL_MANAGEDSAIT,
1662                     NULL
1663           };
1664 
1665           static ConfigTable monitorcfg[] = {
1666                     { NULL, NULL, 0, 0, 0, ARG_IGNORED,
1667                               NULL, NULL, NULL, NULL }
1668           };
1669 
1670           static ConfigOCs monitorocs[] = {
1671                     { "( OLcfgDbOc:4.1 "
1672                               "NAME 'olcMonitorConfig' "
1673                               "DESC 'Monitor backend configuration' "
1674                               "SUP olcDatabaseConfig "
1675                               ")",
1676                                         Cft_Database, monitorcfg },
1677                     { NULL, 0, NULL }
1678           };
1679 
1680           struct m_s {
1681                     char      *schema;
1682                     slap_mask_t flags;
1683                     int       offset;
1684           } moc[] = {
1685                     { "( 1.3.6.1.4.1.4203.666.3.16.1 "
1686                               "NAME 'monitor' "
1687                               "DESC 'OpenLDAP system monitoring' "
1688                               "SUP top STRUCTURAL "
1689                               "MUST cn "
1690                               "MAY ( "
1691                                         "description "
1692                                         "$ seeAlso "
1693                                         "$ labeledURI "
1694                                         "$ monitoredInfo "
1695                                         "$ managedInfo "
1696                                         "$ monitorOverlay "
1697                               ") )", SLAP_OC_OPERATIONAL|SLAP_OC_HIDE,
1698                               offsetof(monitor_info_t, mi_oc_monitor) },
1699                     { "( 1.3.6.1.4.1.4203.666.3.16.2 "
1700                               "NAME 'monitorServer' "
1701                               "DESC 'Server monitoring root entry' "
1702                               "SUP monitor STRUCTURAL )", SLAP_OC_OPERATIONAL|SLAP_OC_HIDE,
1703                               offsetof(monitor_info_t, mi_oc_monitorServer) },
1704                     { "( 1.3.6.1.4.1.4203.666.3.16.3 "
1705                               "NAME 'monitorContainer' "
1706                               "DESC 'monitor container class' "
1707                               "SUP monitor STRUCTURAL )", SLAP_OC_OPERATIONAL|SLAP_OC_HIDE,
1708                               offsetof(monitor_info_t, mi_oc_monitorContainer) },
1709                     { "( 1.3.6.1.4.1.4203.666.3.16.4 "
1710                               "NAME 'monitorCounterObject' "
1711                               "DESC 'monitor counter class' "
1712                               "SUP monitor STRUCTURAL )", SLAP_OC_OPERATIONAL|SLAP_OC_HIDE,
1713                               offsetof(monitor_info_t, mi_oc_monitorCounterObject) },
1714                     { "( 1.3.6.1.4.1.4203.666.3.16.5 "
1715                               "NAME 'monitorOperation' "
1716                               "DESC 'monitor operation class' "
1717                               "SUP monitor STRUCTURAL )", SLAP_OC_OPERATIONAL|SLAP_OC_HIDE,
1718                               offsetof(monitor_info_t, mi_oc_monitorOperation) },
1719                     { "( 1.3.6.1.4.1.4203.666.3.16.6 "
1720                               "NAME 'monitorConnection' "
1721                               "DESC 'monitor connection class' "
1722                               "SUP monitor STRUCTURAL )", SLAP_OC_OPERATIONAL|SLAP_OC_HIDE,
1723                               offsetof(monitor_info_t, mi_oc_monitorConnection) },
1724                     { "( 1.3.6.1.4.1.4203.666.3.16.7 "
1725                               "NAME 'managedObject' "
1726                               "DESC 'monitor managed entity class' "
1727                               "SUP monitor STRUCTURAL )", SLAP_OC_OPERATIONAL|SLAP_OC_HIDE,
1728                               offsetof(monitor_info_t, mi_oc_managedObject) },
1729                     { "( 1.3.6.1.4.1.4203.666.3.16.8 "
1730                               "NAME 'monitoredObject' "
1731                               "DESC 'monitor monitored entity class' "
1732                               "SUP monitor STRUCTURAL )", SLAP_OC_OPERATIONAL|SLAP_OC_HIDE,
1733                               offsetof(monitor_info_t, mi_oc_monitoredObject) },
1734                     { NULL, 0, -1 }
1735           }, mat[] = {
1736                     { "( 1.3.6.1.4.1.4203.666.1.55.1 "
1737                               "NAME 'monitoredInfo' "
1738                               "DESC 'monitored info' "
1739                               /* "SUP name " */
1740                               "EQUALITY caseIgnoreMatch "
1741                               "SUBSTR caseIgnoreSubstringsMatch "
1742                               "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} "
1743                               "NO-USER-MODIFICATION "
1744                               "USAGE dSAOperation )", SLAP_AT_HIDE,
1745                               offsetof(monitor_info_t, mi_ad_monitoredInfo) },
1746                     { "( 1.3.6.1.4.1.4203.666.1.55.2 "
1747                               "NAME 'managedInfo' "
1748                               "DESC 'monitor managed info' "
1749                               "SUP name )", SLAP_AT_HIDE,
1750                               offsetof(monitor_info_t, mi_ad_managedInfo) },
1751                     { "( 1.3.6.1.4.1.4203.666.1.55.3 "
1752                               "NAME 'monitorCounter' "
1753                               "DESC 'monitor counter' "
1754                               "EQUALITY integerMatch "
1755                               "ORDERING integerOrderingMatch "
1756                               "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 "
1757                               "NO-USER-MODIFICATION "
1758                               "USAGE dSAOperation )", SLAP_AT_HIDE,
1759                               offsetof(monitor_info_t, mi_ad_monitorCounter) },
1760                     { "( 1.3.6.1.4.1.4203.666.1.55.4 "
1761                               "NAME 'monitorOpCompleted' "
1762                               "DESC 'monitor completed operations' "
1763                               "SUP monitorCounter "
1764                               "NO-USER-MODIFICATION "
1765                               "USAGE dSAOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
1766                               offsetof(monitor_info_t, mi_ad_monitorOpCompleted) },
1767                     { "( 1.3.6.1.4.1.4203.666.1.55.5 "
1768                               "NAME 'monitorOpInitiated' "
1769                               "DESC 'monitor initiated operations' "
1770                               "SUP monitorCounter "
1771                               "NO-USER-MODIFICATION "
1772                               "USAGE dSAOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
1773                               offsetof(monitor_info_t, mi_ad_monitorOpInitiated) },
1774                     { "( 1.3.6.1.4.1.4203.666.1.55.6 "
1775                               "NAME 'monitorConnectionNumber' "
1776                               "DESC 'monitor connection number' "
1777                               "SUP monitorCounter "
1778                               "NO-USER-MODIFICATION "
1779                               "USAGE dSAOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
1780                               offsetof(monitor_info_t, mi_ad_monitorConnectionNumber) },
1781                     { "( 1.3.6.1.4.1.4203.666.1.55.7 "
1782                               "NAME 'monitorConnectionAuthzDN' "
1783                               "DESC 'monitor connection authorization DN' "
1784                               /* "SUP distinguishedName " */
1785                               "EQUALITY distinguishedNameMatch "
1786                               "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 "
1787                               "NO-USER-MODIFICATION "
1788                               "USAGE dSAOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
1789                               offsetof(monitor_info_t, mi_ad_monitorConnectionAuthzDN) },
1790                     { "( 1.3.6.1.4.1.4203.666.1.55.8 "
1791                               "NAME 'monitorConnectionLocalAddress' "
1792                               "DESC 'monitor connection local address' "
1793                               "SUP monitoredInfo "
1794                               "NO-USER-MODIFICATION "
1795                               "USAGE dSAOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
1796                               offsetof(monitor_info_t, mi_ad_monitorConnectionLocalAddress) },
1797                     { "( 1.3.6.1.4.1.4203.666.1.55.9 "
1798                               "NAME 'monitorConnectionPeerAddress' "
1799                               "DESC 'monitor connection peer address' "
1800                               "SUP monitoredInfo "
1801                               "NO-USER-MODIFICATION "
1802                               "USAGE dSAOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
1803                               offsetof(monitor_info_t, mi_ad_monitorConnectionPeerAddress) },
1804                     { "( 1.3.6.1.4.1.4203.666.1.55.10 "
1805                               "NAME 'monitorTimestamp' "
1806                               "DESC 'monitor timestamp' "
1807                               "EQUALITY generalizedTimeMatch "
1808                               "ORDERING generalizedTimeOrderingMatch "
1809                               "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 "
1810                               "SINGLE-VALUE "
1811                               "NO-USER-MODIFICATION "
1812                               "USAGE dSAOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
1813                               offsetof(monitor_info_t, mi_ad_monitorTimestamp) },
1814                     { "( 1.3.6.1.4.1.4203.666.1.55.11 "
1815                               "NAME 'monitorOverlay' "
1816                               "DESC 'name of overlays defined for a given database' "
1817                               "SUP monitoredInfo "
1818                               "NO-USER-MODIFICATION "
1819                               "USAGE dSAOperation )", SLAP_AT_HIDE,
1820                               offsetof(monitor_info_t, mi_ad_monitorOverlay) },
1821                     { "( 1.3.6.1.4.1.4203.666.1.55.12 "
1822                               "NAME 'readOnly' "
1823                               "DESC 'read/write status of a given database' "
1824                               "EQUALITY booleanMatch "
1825                               "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 "
1826                               "SINGLE-VALUE "
1827                               "USAGE dSAOperation )", SLAP_AT_HIDE,
1828                               offsetof(monitor_info_t, mi_ad_readOnly) },
1829                     { "( 1.3.6.1.4.1.4203.666.1.55.13 "
1830                               "NAME 'restrictedOperation' "
1831                               "DESC 'name of restricted operation for a given database' "
1832                               "SUP managedInfo )", SLAP_AT_HIDE,
1833                               offsetof(monitor_info_t, mi_ad_restrictedOperation ) },
1834                     { "( 1.3.6.1.4.1.4203.666.1.55.14 "
1835                               "NAME 'monitorConnectionProtocol' "
1836                               "DESC 'monitor connection protocol' "
1837                               "SUP monitoredInfo "
1838                               "NO-USER-MODIFICATION "
1839                               "USAGE dSAOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
1840                               offsetof(monitor_info_t, mi_ad_monitorConnectionProtocol) },
1841                     { "( 1.3.6.1.4.1.4203.666.1.55.15 "
1842                               "NAME 'monitorConnectionOpsReceived' "
1843                               "DESC 'monitor number of operations received by the connection' "
1844                               "SUP monitorCounter "
1845                               "NO-USER-MODIFICATION "
1846                               "USAGE dSAOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
1847                               offsetof(monitor_info_t, mi_ad_monitorConnectionOpsReceived) },
1848                     { "( 1.3.6.1.4.1.4203.666.1.55.16 "
1849                               "NAME 'monitorConnectionOpsExecuting' "
1850                               "DESC 'monitor number of operations in execution within the connection' "
1851                               "SUP monitorCounter "
1852                               "NO-USER-MODIFICATION "
1853                               "USAGE dSAOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
1854                               offsetof(monitor_info_t, mi_ad_monitorConnectionOpsExecuting) },
1855                     { "( 1.3.6.1.4.1.4203.666.1.55.17 "
1856                               "NAME 'monitorConnectionOpsPending' "
1857                               "DESC 'monitor number of pending operations within the connection' "
1858                               "SUP monitorCounter "
1859                               "NO-USER-MODIFICATION "
1860                               "USAGE dSAOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
1861                               offsetof(monitor_info_t, mi_ad_monitorConnectionOpsPending) },
1862                     { "( 1.3.6.1.4.1.4203.666.1.55.18 "
1863                               "NAME 'monitorConnectionOpsCompleted' "
1864                               "DESC 'monitor number of operations completed within the connection' "
1865                               "SUP monitorCounter "
1866                               "NO-USER-MODIFICATION "
1867                               "USAGE dSAOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
1868                               offsetof(monitor_info_t, mi_ad_monitorConnectionOpsCompleted) },
1869                     { "( 1.3.6.1.4.1.4203.666.1.55.19 "
1870                               "NAME 'monitorConnectionGet' "
1871                               "DESC 'number of times connection_get() was called so far' "
1872                               "SUP monitorCounter "
1873                               "NO-USER-MODIFICATION "
1874                               "USAGE dSAOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
1875                               offsetof(monitor_info_t, mi_ad_monitorConnectionGet) },
1876                     { "( 1.3.6.1.4.1.4203.666.1.55.20 "
1877                               "NAME 'monitorConnectionRead' "
1878                               "DESC 'number of times connection_read() was called so far' "
1879                               "SUP monitorCounter "
1880                               "NO-USER-MODIFICATION "
1881                               "USAGE dSAOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
1882                               offsetof(monitor_info_t, mi_ad_monitorConnectionRead) },
1883                     { "( 1.3.6.1.4.1.4203.666.1.55.21 "
1884                               "NAME 'monitorConnectionWrite' "
1885                               "DESC 'number of times connection_write() was called so far' "
1886                               "SUP monitorCounter "
1887                               "NO-USER-MODIFICATION "
1888                               "USAGE dSAOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
1889                               offsetof(monitor_info_t, mi_ad_monitorConnectionWrite) },
1890                     { "( 1.3.6.1.4.1.4203.666.1.55.22 "
1891                               "NAME 'monitorConnectionMask' "
1892                               "DESC 'monitor connection mask' "
1893                               "SUP monitoredInfo "
1894                               "NO-USER-MODIFICATION "
1895                               "USAGE dSAOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
1896                               offsetof(monitor_info_t, mi_ad_monitorConnectionMask) },
1897                     { "( 1.3.6.1.4.1.4203.666.1.55.23 "
1898                               "NAME 'monitorConnectionListener' "
1899                               "DESC 'monitor connection listener' "
1900                               "SUP monitoredInfo "
1901                               "NO-USER-MODIFICATION "
1902                               "USAGE dSAOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
1903                               offsetof(monitor_info_t, mi_ad_monitorConnectionListener) },
1904                     { "( 1.3.6.1.4.1.4203.666.1.55.24 "
1905                               "NAME 'monitorConnectionPeerDomain' "
1906                               "DESC 'monitor connection peer domain' "
1907                               "SUP monitoredInfo "
1908                               "NO-USER-MODIFICATION "
1909                               "USAGE dSAOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
1910                               offsetof(monitor_info_t, mi_ad_monitorConnectionPeerDomain) },
1911                     { "( 1.3.6.1.4.1.4203.666.1.55.25 "
1912                               "NAME 'monitorConnectionStartTime' "
1913                               "DESC 'monitor connection start time' "
1914                               "SUP monitorTimestamp "
1915                               "SINGLE-VALUE "
1916                               "NO-USER-MODIFICATION "
1917                               "USAGE dSAOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
1918                               offsetof(monitor_info_t, mi_ad_monitorConnectionStartTime) },
1919                     { "( 1.3.6.1.4.1.4203.666.1.55.26 "
1920                               "NAME 'monitorConnectionActivityTime' "
1921                               "DESC 'monitor connection activity time' "
1922                               "SUP monitorTimestamp "
1923                               "SINGLE-VALUE "
1924                               "NO-USER-MODIFICATION "
1925                               "USAGE dSAOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
1926                               offsetof(monitor_info_t, mi_ad_monitorConnectionActivityTime) },
1927                     { "( 1.3.6.1.4.1.4203.666.1.55.27 "
1928                               "NAME 'monitorIsShadow' "
1929                               "DESC 'TRUE if the database is shadow' "
1930                               "EQUALITY booleanMatch "
1931                               "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 "
1932                               "SINGLE-VALUE "
1933                               "USAGE dSAOperation )", SLAP_AT_HIDE,
1934                               offsetof(monitor_info_t, mi_ad_monitorIsShadow) },
1935                     { "( 1.3.6.1.4.1.4203.666.1.55.28 "
1936                               "NAME 'monitorUpdateRef' "
1937                               "DESC 'update referral for shadow databases' "
1938                               "SUP monitoredInfo "
1939                               "SINGLE-VALUE "
1940                               "USAGE dSAOperation )", SLAP_AT_HIDE,
1941                               offsetof(monitor_info_t, mi_ad_monitorUpdateRef) },
1942                     { "( 1.3.6.1.4.1.4203.666.1.55.29 "
1943                               "NAME 'monitorRuntimeConfig' "
1944                               "DESC 'TRUE if component allows runtime configuration' "
1945                               "EQUALITY booleanMatch "
1946                               "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 "
1947                               "SINGLE-VALUE "
1948                               "USAGE dSAOperation )", SLAP_AT_HIDE,
1949                               offsetof(monitor_info_t, mi_ad_monitorRuntimeConfig) },
1950                     { "( 1.3.6.1.4.1.4203.666.1.55.30 "
1951                               "NAME 'monitorSuperiorDN' "
1952                               "DESC 'monitor superior DN' "
1953                               /* "SUP distinguishedName " */
1954                               "EQUALITY distinguishedNameMatch "
1955                               "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 "
1956                               "NO-USER-MODIFICATION "
1957                               "USAGE dSAOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
1958                               offsetof(monitor_info_t, mi_ad_monitorSuperiorDN) },
1959                     { NULL, 0, -1 }
1960           };
1961 
1962           static struct {
1963                     char                          *name;
1964                     char                          *oid;
1965           }                   s_oid[] = {
1966                     { "olmAttributes",                      "1.3.6.1.4.1.4203.666.1.55" },
1967                     { "olmSubSystemAttributes",             "olmAttributes:0" },
1968                     { "olmGenericAttributes",               "olmSubSystemAttributes:0" },
1969                     { "olmDatabaseAttributes",              "olmSubSystemAttributes:1" },
1970                     { "olmOverlayAttributes",               "olmSubSystemAttributes:2" },
1971                     { "olmModuleAttributes",                "olmSubSystemAttributes:3" },
1972 
1973                     /* for example, back-mdb specific attrs
1974                      * are in "olmDatabaseAttributes:12"
1975                      *
1976                      * NOTE: developers, please record here OID assignments
1977                      * for other modules */
1978 
1979                     { "olmObjectClasses",                             "1.3.6.1.4.1.4203.666.3.16" },
1980                     { "olmSubSystemObjectClasses",                    "olmObjectClasses:0" },
1981                     { "olmGenericObjectClasses",            "olmSubSystemObjectClasses:0" },
1982                     { "olmDatabaseObjectClasses",           "olmSubSystemObjectClasses:1" },
1983                     { "olmOverlayObjectClasses",            "olmSubSystemObjectClasses:2" },
1984                     { "olmModuleObjectClasses",                       "olmSubSystemObjectClasses:3" },
1985 
1986                     /* for example, back-mdb specific objectClasses
1987                      * are in "olmDatabaseObjectClasses:12"
1988                      *
1989                      * NOTE: developers, please record here OID assignments
1990                      * for other modules */
1991 
1992                     { NULL }
1993           };
1994 
1995           int                           i, rc;
1996           monitor_info_t                *mi = &monitor_info;
1997           ConfigArgs c;
1998           char      *argv[ 3 ];
1999 
2000           argv[ 0 ] = "monitor";
2001           c.argv = argv;
2002           c.argc = 3;
2003           c.fname = argv[0];
2004 
2005           for ( i = 0; s_oid[ i ].name; i++ ) {
2006                     argv[ 1 ] = s_oid[ i ].name;
2007                     argv[ 2 ] = s_oid[ i ].oid;
2008 
2009                     if ( parse_oidm( &c, 0, NULL ) != 0 ) {
2010                               Debug( LDAP_DEBUG_ANY,
2011                                         "monitor_back_initialize: unable to add "
2012                                         "objectIdentifier \"%s=%s\"\n",
2013                                         s_oid[ i ].name, s_oid[ i ].oid );
2014                               return 1;
2015                     }
2016           }
2017 
2018           /* schema integration */
2019           for ( i = 0; mat[ i ].schema; i++ ) {
2020                     int                           code;
2021                     AttributeDescription **ad =
2022                               ((AttributeDescription **)&(((char *)mi)[ mat[ i ].offset ]));
2023 
2024                     *ad = NULL;
2025                     code = register_at( mat[ i ].schema, ad, 0 );
2026 
2027                     if ( code ) {
2028                               Debug( LDAP_DEBUG_ANY,
2029                                         "monitor_back_db_init: register_at failed\n" );
2030                               return -1;
2031                     }
2032                     (*ad)->ad_type->sat_flags |= mat[ i ].flags;
2033           }
2034 
2035           for ( i = 0; moc[ i ].schema; i++ ) {
2036                     int                           code;
2037                     ObjectClass                   **Oc =
2038                               ((ObjectClass **)&(((char *)mi)[ moc[ i ].offset ]));
2039 
2040                     code = register_oc( moc[ i ].schema, Oc, 0 );
2041                     if ( code ) {
2042                               Debug( LDAP_DEBUG_ANY,
2043                                         "monitor_back_db_init: register_oc failed\n" );
2044                               return -1;
2045                     }
2046                     (*Oc)->soc_flags |= moc[ i ].flags;
2047           }
2048 
2049           bi->bi_controls = controls;
2050 
2051           bi->bi_init = 0;
2052           bi->bi_open = 0;
2053           bi->bi_config = monitor_back_config;
2054           bi->bi_close = 0;
2055           bi->bi_destroy = 0;
2056 
2057           bi->bi_db_init = monitor_back_db_init;
2058 #if 0
2059           bi->bi_db_config = monitor_back_db_config;
2060 #endif
2061           bi->bi_db_open = monitor_back_db_open;
2062           bi->bi_db_close = 0;
2063           bi->bi_db_destroy = monitor_back_db_destroy;
2064 
2065           bi->bi_op_bind = monitor_back_bind;
2066           bi->bi_op_unbind = 0;
2067           bi->bi_op_search = monitor_back_search;
2068           bi->bi_op_compare = monitor_back_compare;
2069           bi->bi_op_modify = monitor_back_modify;
2070           bi->bi_op_modrdn = 0;
2071           bi->bi_op_add = 0;
2072           bi->bi_op_delete = 0;
2073           bi->bi_op_abandon = 0;
2074 
2075           bi->bi_extended = 0;
2076 
2077           bi->bi_entry_release_rw = monitor_back_release;
2078           bi->bi_chk_referrals = 0;
2079           bi->bi_operational = monitor_back_operational;
2080 
2081           /*
2082            * hooks for slap tools
2083            */
2084           bi->bi_tool_entry_open = 0;
2085           bi->bi_tool_entry_close = 0;
2086           bi->bi_tool_entry_first = 0;
2087           bi->bi_tool_entry_first_x = 0;
2088           bi->bi_tool_entry_next = 0;
2089           bi->bi_tool_entry_get = 0;
2090           bi->bi_tool_entry_put = 0;
2091           bi->bi_tool_entry_reindex = 0;
2092           bi->bi_tool_sync = 0;
2093           bi->bi_tool_dn2id_get = 0;
2094           bi->bi_tool_entry_modify = 0;
2095 
2096           bi->bi_connection_init = 0;
2097           bi->bi_connection_destroy = 0;
2098 
2099           bi->bi_extra = (void *)&monitor_extra;
2100 
2101           /*
2102            * configuration objectClasses (fake)
2103            */
2104           bi->bi_cf_ocs = monitorocs;
2105 
2106           rc = config_register_schema( monitorcfg, monitorocs );
2107           if ( rc ) {
2108                     return rc;
2109           }
2110 
2111           return 0;
2112 }
2113 
2114 int
monitor_back_db_init(BackendDB * be,ConfigReply * c)2115 monitor_back_db_init(
2116           BackendDB *be,
2117           ConfigReply         *c)
2118 {
2119           int                           rc;
2120           struct berval                 dn = BER_BVC( SLAPD_MONITOR_DN ),
2121                                         pdn,
2122                                         ndn;
2123           BackendDB           *be2;
2124 
2125           monitor_subsys_t    *ms;
2126 
2127           /*
2128            * database monitor can be defined once only
2129            */
2130           if ( be_monitor != NULL ) {
2131                     if (c) {
2132                               snprintf(c->msg, sizeof(c->msg),"only one monitor database allowed");
2133                     }
2134                     return( -1 );
2135           }
2136           be_monitor = be;
2137 
2138           /*
2139            * register subsys
2140            */
2141           for ( ms = known_monitor_subsys; ms->mss_name != NULL; ms++ ) {
2142                     if ( monitor_back_register_subsys( ms ) ) {
2143                               return -1;
2144                     }
2145           }
2146 
2147           /* indicate system schema supported */
2148           SLAP_BFLAGS(be) |= SLAP_BFLAG_MONITOR;
2149 
2150           rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn, NULL );
2151           if( rc != LDAP_SUCCESS ) {
2152                     Debug( LDAP_DEBUG_ANY,
2153                               "unable to normalize/pretty monitor DN \"%s\" (%d)\n",
2154                               dn.bv_val, rc );
2155                     return -1;
2156           }
2157 
2158           ber_bvarray_add( &be->be_suffix, &pdn );
2159           ber_bvarray_add( &be->be_nsuffix, &ndn );
2160 
2161           /* NOTE: only one monitor database is allowed,
2162            * so we use static storage */
2163           ldap_pvt_thread_mutex_init( &monitor_info.mi_cache_mutex );
2164 
2165           be->be_private = &monitor_info;
2166 
2167           be2 = select_backend( &ndn, 0 );
2168           if ( be2 != be ) {
2169                     char      *type = be2->bd_info->bi_type;
2170 
2171                     if ( overlay_is_over( be2 ) ) {
2172                               slap_overinfo       *oi = (slap_overinfo *)be2->bd_info->bi_private;
2173                               type = oi->oi_orig->bi_type;
2174                     }
2175 
2176                     if (c) {
2177                               snprintf(c->msg, sizeof(c->msg),
2178                                                   "\"monitor\" database serving namingContext \"%s\" "
2179                                                   "is hidden by \"%s\" database serving namingContext \"%s\".\n",
2180                                                   pdn.bv_val, type, be2->be_nsuffix[ 0 ].bv_val );
2181                     }
2182                     return -1;
2183           }
2184 
2185           return 0;
2186 }
2187 
2188 static void
monitor_back_destroy_limbo_entry(entry_limbo_t * el,int dispose)2189 monitor_back_destroy_limbo_entry(
2190           entry_limbo_t       *el,
2191           int                 dispose )
2192 {
2193           if ( el->el_e ) {
2194                     entry_free( el->el_e );
2195           }
2196           if ( el->el_a ) {
2197                     attrs_free( el->el_a );
2198           }
2199           if ( !BER_BVISNULL( &el->el_nbase ) ) {
2200                     ber_memfree( el->el_nbase.bv_val );
2201           }
2202           if ( !BER_BVISNULL( &el->el_filter ) ) {
2203                     ber_memfree( el->el_filter.bv_val );
2204           }
2205 
2206           /* NOTE: callbacks are not copied; so only free them
2207            * if disposing of */
2208           if ( el->el_cb && dispose != 0 ) {
2209                     monitor_callback_t *next;
2210 
2211                     for ( ; el->el_cb; el->el_cb = next ) {
2212                               next = el->el_cb->mc_next;
2213                               if ( el->el_cb->mc_dispose ) {
2214                                         el->el_cb->mc_dispose( &el->el_cb->mc_private );
2215                               }
2216                               ch_free( el->el_cb );
2217                     }
2218           }
2219 
2220           ch_free( el );
2221 }
2222 
2223 int
monitor_back_db_open(BackendDB * be,ConfigReply * cr)2224 monitor_back_db_open(
2225           BackendDB *be,
2226           ConfigReply         *cr)
2227 {
2228           monitor_info_t                *mi = (monitor_info_t *)be->be_private;
2229           struct monitor_subsys_t       **ms;
2230           Entry                         *e, **ep, *root;
2231           monitor_entry_t               *mp;
2232           int                           i;
2233           struct berval                 bv, rdn = BER_BVC(SLAPD_MONITOR_DN);
2234           struct tm           tms;
2235           static char                   tmbuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];
2236           struct berval       desc[] = {
2237                     BER_BVC("This subtree contains monitoring/managing objects."),
2238                     BER_BVC("This object contains information about this server."),
2239                     BER_BVC("Most of the information is held in operational"
2240                     " attributes, which must be explicitly requested."),
2241                     BER_BVNULL };
2242 
2243           int                           retcode = 0;
2244 
2245           assert( be_monitor != NULL );
2246           if ( be != be_monitor ) {
2247                     be_monitor = be;
2248           }
2249 
2250           /*
2251            * Start
2252            */
2253           ldap_pvt_gmtime( &starttime, &tms );
2254           lutil_gentime( tmbuf, sizeof(tmbuf), &tms );
2255 
2256           mi->mi_startTime.bv_val = tmbuf;
2257           mi->mi_startTime.bv_len = strlen( tmbuf );
2258 
2259           if ( BER_BVISEMPTY( &be->be_rootdn ) ) {
2260                     BER_BVSTR( &mi->mi_creatorsName, SLAPD_ANONYMOUS );
2261                     BER_BVSTR( &mi->mi_ncreatorsName, SLAPD_ANONYMOUS );
2262           } else {
2263                     mi->mi_creatorsName = be->be_rootdn;
2264                     mi->mi_ncreatorsName = be->be_rootndn;
2265           }
2266 
2267           /*
2268            * creates the "cn=Monitor" entry
2269            */
2270           e = monitor_entry_stub( NULL, NULL, &rdn, mi->mi_oc_monitorServer,
2271                     NULL, NULL );
2272 
2273           if ( e == NULL) {
2274                     Debug( LDAP_DEBUG_ANY,
2275                               "unable to create \"%s\" entry\n",
2276                               SLAPD_MONITOR_DN );
2277                     return( -1 );
2278           }
2279 
2280           attr_merge_normalize( e, slap_schema.si_ad_description, desc, NULL );
2281 
2282           bv.bv_val = strchr( (char *) Versionstr, '$' );
2283           if ( bv.bv_val != NULL ) {
2284                     char      *end;
2285 
2286                     bv.bv_val++;
2287                     for ( ; bv.bv_val[ 0 ] == ' '; bv.bv_val++ )
2288                               ;
2289 
2290                     end = strchr( bv.bv_val, '$' );
2291                     if ( end != NULL ) {
2292                               end--;
2293 
2294                               for ( ; end > bv.bv_val && end[ 0 ] == ' '; end-- )
2295                                         ;
2296 
2297                               end++;
2298 
2299                               bv.bv_len = end - bv.bv_val;
2300 
2301                     } else {
2302                               bv.bv_len = strlen( bv.bv_val );
2303                     }
2304 
2305                     if ( attr_merge_normalize_one( e, mi->mi_ad_monitoredInfo,
2306                                                   &bv, NULL ) ) {
2307                               Debug( LDAP_DEBUG_ANY,
2308                                         "unable to add monitoredInfo to \"%s\" entry\n",
2309                                         SLAPD_MONITOR_DN );
2310                               return( -1 );
2311                     }
2312           }
2313 
2314           mp = monitor_entrypriv_create();
2315           if ( mp == NULL ) {
2316                     return -1;
2317           }
2318           e->e_private = ( void * )mp;
2319           ep = &mp->mp_children;
2320 
2321           if ( monitor_cache_add( mi, e ) ) {
2322                     Debug( LDAP_DEBUG_ANY,
2323                               "unable to add entry \"%s\" to cache\n",
2324                               SLAPD_MONITOR_DN );
2325                     return -1;
2326           }
2327           root = e;
2328 
2329           /*
2330            * Create all the subsystem specific entries
2331            */
2332           for ( i = 0; monitor_subsys[ i ] != NULL; i++ ) {
2333                     int                 len = strlen( monitor_subsys[ i ]->mss_name );
2334                     struct berval       dn;
2335                     int                 rc;
2336 
2337                     dn.bv_len = len + sizeof( "cn=" ) - 1;
2338                     dn.bv_val = ch_calloc( sizeof( char ), dn.bv_len + 1 );
2339                     strcpy( dn.bv_val, "cn=" );
2340                     strcat( dn.bv_val, monitor_subsys[ i ]->mss_name );
2341                     rc = dnPretty( NULL, &dn, &monitor_subsys[ i ]->mss_rdn, NULL );
2342                     free( dn.bv_val );
2343                     if ( rc != LDAP_SUCCESS ) {
2344                               Debug( LDAP_DEBUG_ANY,
2345                                         "monitor RDN \"%s\" is invalid\n",
2346                                         dn.bv_val );
2347                               return( -1 );
2348                     }
2349 
2350                     e = monitor_entry_stub( &root->e_name, &root->e_nname,
2351                               &monitor_subsys[ i ]->mss_rdn, mi->mi_oc_monitorContainer,
2352                               NULL, NULL );
2353 
2354                     if ( e == NULL) {
2355                               Debug( LDAP_DEBUG_ANY,
2356                                         "unable to create \"%s\" entry\n",
2357                                         monitor_subsys[ i ]->mss_dn.bv_val );
2358                               return( -1 );
2359                     }
2360                     monitor_subsys[i]->mss_dn = e->e_name;
2361                     monitor_subsys[i]->mss_ndn = e->e_nname;
2362 
2363                     if ( !BER_BVISNULL( &monitor_subsys[ i ]->mss_desc[ 0 ] ) ) {
2364                               attr_merge_normalize( e, slap_schema.si_ad_description,
2365                                                   monitor_subsys[ i ]->mss_desc, NULL );
2366                     }
2367 
2368                     mp = monitor_entrypriv_create();
2369                     if ( mp == NULL ) {
2370                               return -1;
2371                     }
2372                     e->e_private = ( void * )mp;
2373                     mp->mp_info = monitor_subsys[ i ];
2374                     mp->mp_flags = monitor_subsys[ i ]->mss_flags;
2375 
2376                     if ( monitor_cache_add( mi, e ) ) {
2377                               Debug( LDAP_DEBUG_ANY,
2378                                         "unable to add entry \"%s\" to cache\n",
2379                                         monitor_subsys[ i ]->mss_dn.bv_val );
2380                               return -1;
2381                     }
2382 
2383                     *ep = e;
2384                     ep = &mp->mp_next;
2385           }
2386 
2387           assert( be != NULL );
2388 
2389           be->be_private = mi;
2390 
2391           /*
2392            * opens the monitor backend subsystems
2393            */
2394           for ( ms = monitor_subsys; ms[ 0 ] != NULL; ms++ ) {
2395                     if ( ms[ 0 ]->mss_open && ms[ 0 ]->mss_open( be, ms[ 0 ] ) ) {
2396                               return( -1 );
2397                     }
2398                     ms[ 0 ]->mss_flags |= MONITOR_F_OPENED;
2399           }
2400 
2401           monitor_subsys_opened = 1;
2402 
2403           if ( mi->mi_entry_limbo ) {
2404                     entry_limbo_t       *el = mi->mi_entry_limbo;
2405 
2406                     for ( ; el; ) {
2407                               entry_limbo_t       *tmp;
2408                               int                 rc;
2409 
2410                               switch ( el->el_type ) {
2411                               case LIMBO_ENTRY:
2412                                         rc = monitor_back_register_entry(
2413                                                             el->el_e,
2414                                                             el->el_cb,
2415                                                             el->el_mss,
2416                                                             el->el_flags );
2417                                         break;
2418 
2419                               case LIMBO_ENTRY_PARENT:
2420                                         rc = monitor_back_register_entry_parent(
2421                                                             el->el_e,
2422                                                             el->el_cb,
2423                                                             el->el_mss,
2424                                                             el->el_flags,
2425                                                             &el->el_nbase,
2426                                                             el->el_scope,
2427                                                             &el->el_filter );
2428                                         break;
2429 
2430 
2431                               case LIMBO_ATTRS:
2432                                         rc = monitor_back_register_entry_attrs(
2433                                                             el->el_ndn,
2434                                                             el->el_a,
2435                                                             el->el_cb,
2436                                                             &el->el_nbase,
2437                                                             el->el_scope,
2438                                                             &el->el_filter );
2439                                         break;
2440 
2441                               case LIMBO_CB:
2442                                         rc = monitor_back_register_entry_callback(
2443                                                             el->el_ndn,
2444                                                             el->el_cb,
2445                                                             &el->el_nbase,
2446                                                             el->el_scope,
2447                                                             &el->el_filter );
2448                                         break;
2449 
2450                               case LIMBO_BACKEND:
2451                                         rc = monitor_back_register_backend( el->el_bi );
2452                                         break;
2453 
2454                               case LIMBO_DATABASE:
2455                                         rc = monitor_back_register_database( el->el_be, el->el_ndn );
2456                                         break;
2457 
2458                               case LIMBO_OVERLAY_INFO:
2459                                         rc = monitor_back_register_overlay_info( el->el_on );
2460                                         break;
2461 
2462                               case LIMBO_OVERLAY:
2463                                         rc = monitor_back_register_overlay( el->el_be, el->el_on, el->el_ndn );
2464                                         break;
2465 
2466                               case LIMBO_SUBSYS:
2467                                         rc = monitor_back_register_subsys( el->el_mss );
2468                                         break;
2469 
2470                               default:
2471                                         assert( 0 );
2472                               }
2473 
2474                               tmp = el;
2475                               el = el->el_next;
2476                               monitor_back_destroy_limbo_entry( tmp, rc );
2477 
2478                               if ( rc != 0 ) {
2479                                         /* try all, but report error at end */
2480                                         retcode = 1;
2481                               }
2482                     }
2483 
2484                     mi->mi_entry_limbo = NULL;
2485           }
2486 
2487           return retcode;
2488 }
2489 
2490 int
monitor_back_config(BackendInfo * bi,const char * fname,int lineno,int argc,char ** argv)2491 monitor_back_config(
2492           BackendInfo         *bi,
2493           const char          *fname,
2494           int                 lineno,
2495           int                 argc,
2496           char                **argv )
2497 {
2498           /*
2499            * eventually, will hold backend specific configuration parameters
2500            */
2501           return SLAP_CONF_UNKNOWN;
2502 }
2503 
2504 #if 0
2505 int
2506 monitor_back_db_config(
2507           Backend     *be,
2508           const char  *fname,
2509           int         lineno,
2510           int         argc,
2511           char        **argv )
2512 {
2513           monitor_info_t      *mi = ( monitor_info_t * )be->be_private;
2514 
2515           /*
2516            * eventually, will hold database specific configuration parameters
2517            */
2518           return SLAP_CONF_UNKNOWN;
2519 }
2520 #endif
2521 
2522 int
monitor_back_db_destroy(BackendDB * be,ConfigReply * cr)2523 monitor_back_db_destroy(
2524           BackendDB *be,
2525           ConfigReply         *cr)
2526 {
2527           monitor_info_t      *mi = ( monitor_info_t * )be->be_private;
2528 
2529           if ( mi == NULL ) {
2530                     return -1;
2531           }
2532 
2533           /*
2534            * FIXME: destroys all the data
2535            */
2536           /* NOTE: mi points to static storage; don't free it */
2537 
2538           (void)monitor_cache_destroy( mi );
2539 
2540           if ( monitor_subsys ) {
2541                     int       i;
2542 
2543                     for ( i = 0; monitor_subsys[ i ] != NULL; i++ ) {
2544                               if ( monitor_subsys[ i ]->mss_destroy ) {
2545                                         monitor_subsys[ i ]->mss_destroy( be, monitor_subsys[ i ] );
2546                               }
2547 
2548                               if ( !BER_BVISNULL( &monitor_subsys[ i ]->mss_rdn ) ) {
2549                                         ch_free( monitor_subsys[ i ]->mss_rdn.bv_val );
2550                               }
2551                     }
2552 
2553                     ch_free( monitor_subsys );
2554           }
2555 
2556           if ( mi->mi_entry_limbo ) {
2557                     entry_limbo_t       *el = mi->mi_entry_limbo;
2558 
2559                     for ( ; el; ) {
2560                               entry_limbo_t *tmp = el;
2561                               el = el->el_next;
2562                               monitor_back_destroy_limbo_entry( tmp, 1 );
2563                     }
2564           }
2565 
2566           ldap_pvt_thread_mutex_destroy( &monitor_info.mi_cache_mutex );
2567 
2568           be->be_private = NULL;
2569 
2570           return 0;
2571 }
2572