xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/back-monitor/init.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
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