init.c 35 KB
Newer Older
1
/* init.c - initialize monitor backend */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
2
3
4
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 *
Kurt Zeilenga's avatar
Kurt Zeilenga committed
5
 * Copyright 2001-2005 The OpenLDAP Foundation.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
6
 * Portions Copyright 2001-2003 Pierangelo Masarati.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted only as authorized by the OpenLDAP
 * Public License.
 *
 * A copy of this license is available in file LICENSE in the
 * top-level directory of the distribution or, alternatively, at
 * <http://www.OpenLDAP.org/license.html>.
 */
/* ACKNOWLEDGEMENTS:
 * This work was initially developed by Pierangelo Masarati for inclusion
 * in OpenLDAP Software.
 */
21
22
23
24

#include "portable.h"

#include <stdio.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
25
#include <ac/string.h>
26

27
#include <lutil.h>
28
#include "slap.h"
29
#include "lber_pvt.h"
30
31
#include "back-monitor.h"

32
#undef INTEGRATE_CORE_SCHEMA
33

34
35
/*
 * used by many functions to add description to entries
36
37
38
39
 *
 * WARNING: be_monitor may change as new databases are added,
 * so it should not be used outside monitor_back_db_init()
 * until monitor_back_db_open is called.
40
 */
41
BackendDB *be_monitor = NULL;
42

43
static struct monitor_subsys_t	**monitor_subsys = NULL;
44
45
static int			monitor_subsys_opened = 0;

46
47
/*
 * subsystem data
48
49
50
51
52
53
 *
 * the known subsystems are added to the subsystems
 * array at backend initialization; other subsystems
 * may be added by calling monitor_back_register_subsys()
 * before the database is opened (e.g. by other backends
 * or by overlays or modules).
54
 */
55
static struct monitor_subsys_t known_monitor_subsys[] = {
56
	{ 
57
		SLAPD_MONITOR_BACKEND_NAME, 
58
		BER_BVNULL, BER_BVNULL, BER_BVNULL,
59
60
61
		MONITOR_F_PERSISTENT_CH,
		monitor_subsys_backend_init,
		NULL,   /* update */
62
63
		NULL,   /* create */
		NULL	/* modify */
64
       	}, { 
65
		SLAPD_MONITOR_CONN_NAME,
66
		BER_BVNULL, BER_BVNULL, BER_BVNULL,
67
68
69
		MONITOR_F_VOLATILE_CH,
		monitor_subsys_conn_init,
		monitor_subsys_conn_update,
70
71
		monitor_subsys_conn_create,
		NULL	/* modify */
72
       	}, { 
73
		SLAPD_MONITOR_DATABASE_NAME, 	
74
		BER_BVNULL, BER_BVNULL, BER_BVNULL,
75
		MONITOR_F_PERSISTENT_CH,
76
77
78
79
80
81
82
83
84
85
86
		monitor_subsys_database_init,
		NULL,   /* update */
		NULL,   /* create */
		monitor_subsys_database_modify
       	}, { 
		SLAPD_MONITOR_LISTENER_NAME, 	
		BER_BVNULL, BER_BVNULL, BER_BVNULL,
		MONITOR_F_PERSISTENT_CH,
		monitor_subsys_listener_init,
		NULL,	/* update */
		NULL,	/* create */
87
88
		NULL	/* modify */
       	}, { 
89
		SLAPD_MONITOR_LOG_NAME,
90
		BER_BVNULL, BER_BVNULL, BER_BVNULL,
91
92
93
94
95
		MONITOR_F_NONE,
		monitor_subsys_log_init,
		NULL,	/* update */
		NULL,   /* create */
		monitor_subsys_log_modify
96
       	}, { 
97
		SLAPD_MONITOR_OPS_NAME,
98
		BER_BVNULL, BER_BVNULL, BER_BVNULL,
Pierangelo Masarati's avatar
Pierangelo Masarati committed
99
		MONITOR_F_PERSISTENT_CH,
100
101
102
103
104
		monitor_subsys_ops_init,
		monitor_subsys_ops_update,
		NULL,   /* create */
		NULL,	/* modify */
       	}, { 
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
		SLAPD_MONITOR_OVERLAY_NAME,
		BER_BVNULL, BER_BVNULL, BER_BVNULL,
		MONITOR_F_PERSISTENT_CH,
		monitor_subsys_overlay_init,
		NULL,	/* update */
		NULL,   /* create */
		NULL,	/* modify */
	}, { 
		SLAPD_MONITOR_SASL_NAME, 	
		BER_BVNULL, BER_BVNULL, BER_BVNULL,
		MONITOR_F_NONE,
		NULL,   /* init */
		NULL,   /* update */
		NULL,   /* create */
		NULL	/* modify */
       	}, { 
		SLAPD_MONITOR_SENT_NAME,
122
		BER_BVNULL, BER_BVNULL, BER_BVNULL,
Pierangelo Masarati's avatar
Pierangelo Masarati committed
123
		MONITOR_F_PERSISTENT_CH,
124
125
126
127
		monitor_subsys_sent_init,
		monitor_subsys_sent_update,
		NULL,   /* create */
		NULL,	/* modify */
Pierangelo Masarati's avatar
Pierangelo Masarati committed
128
       	}, { 
129
130
131
132
133
134
135
136
137
		SLAPD_MONITOR_THREAD_NAME, 	
		BER_BVNULL, BER_BVNULL, BER_BVNULL,
		MONITOR_F_PERSISTENT_CH,
		monitor_subsys_thread_init,
		monitor_subsys_thread_update,
		NULL,   /* create */
		NULL	/* modify */
       	}, { 
		SLAPD_MONITOR_TIME_NAME,
138
		BER_BVNULL, BER_BVNULL, BER_BVNULL,
Pierangelo Masarati's avatar
Pierangelo Masarati committed
139
140
141
142
143
		MONITOR_F_PERSISTENT_CH,
		monitor_subsys_time_init,
		monitor_subsys_time_update,
		NULL,   /* create */
		NULL,	/* modify */
144
       	}, { 
145
		SLAPD_MONITOR_TLS_NAME,
146
		BER_BVNULL, BER_BVNULL, BER_BVNULL,
147
148
149
		MONITOR_F_NONE,
		NULL,   /* init */
		NULL,   /* update */
150
		NULL,   /* create */
151
152
153
154
155
156
157
158
159
160
		NULL	/* modify */
       	}, { 
		SLAPD_MONITOR_RWW_NAME,
		BER_BVNULL, BER_BVNULL, BER_BVNULL,
		MONITOR_F_PERSISTENT_CH,
		monitor_subsys_rww_init,
		monitor_subsys_rww_update,
		NULL, 	/* create */
		NULL	/* modify */
       	}, { NULL }
161
162
};

163
int
164
monitor_back_register_subsys( monitor_subsys_t *ms )
165
166
167
168
169
170
171
172
173
{
	int	i = 0;

	if ( monitor_subsys ) {
		for ( ; monitor_subsys[ i ] != NULL; i++ )
			/* just count'em */ ;
	}

	monitor_subsys = ch_realloc( monitor_subsys,
174
			( 2 + i ) * sizeof( monitor_subsys_t * ) );
175
176
177
178
179
180
181
182

	if ( monitor_subsys == NULL ) {
		return -1;
	}

	monitor_subsys[ i ] = ms;
	monitor_subsys[ i + 1 ] = NULL;

183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
	/* if a subsystem is registered __AFTER__ subsystem 
	 * initialization (depending on the sequence the databases
	 * are listed in slapd.conf), init it */
	if ( monitor_subsys_opened ) {

		/* FIXME: this should only be possible
		 * if be_monitor is already initialized */
		assert( be_monitor );

		if ( ms->mss_open && ( *ms->mss_open )( be_monitor, ms ) ) {
			return -1;
		}

		ms->mss_flags |= MONITOR_F_OPENED;
	}

199
200
201
	return 0;
}

202
203
204
205
206
207
enum {
	LIMBO_ENTRY,
	LIMBO_ATTRS,
	LIMBO_CB
};

208
typedef struct entry_limbo_t {
209
	int			el_type;
210
	Entry			*el_e;
211
212
213
214
215
	Attribute		*el_a;
	struct berval		el_ndn;
	struct berval		el_base;
	int			el_scope;
	struct berval		el_filter;
216
217
218
219
220
221
222
	monitor_callback_t	*el_cb;
	struct entry_limbo_t	*el_next;
} entry_limbo_t;

int
monitor_back_register_entry(
		Entry			*e,
223
		monitor_callback_t	*cb )
224
225
226
227
228
229
230
231
{
	monitor_info_t 	*mi = ( monitor_info_t * )be_monitor->be_private;

	assert( mi != NULL );
	assert( e != NULL );
	assert( e->e_private == NULL );
	
	if ( monitor_subsys_opened ) {
232
233
234
235
		Entry		*e_parent = NULL,
				*e_new = NULL,
				**ep = NULL;
		struct berval	pdn = BER_BVNULL;
236
		monitor_entry_t *mp = NULL,
237
238
				*mp_parent = NULL;
		int		rc = 0;
239

240
		if ( monitor_cache_get( mi, &e->e_nname, &e_parent ) == 0 ) {
241
242
243
244
245
			/* entry exists */
			Debug( LDAP_DEBUG_ANY,
				"monitor_back_register_entry(\"%s\"): "
				"entry exists\n",
				e->e_name.bv_val, 0, 0 );
246
			monitor_cache_release( mi, e_parent );
247
248
249
250
			return -1;
		}

		dnParent( &e->e_nname, &pdn );
251
		if ( monitor_cache_get( mi, &pdn, &e_parent ) != 0 ) {
252
253
254
255
256
257
258
259
			/* parent does not exist */
			Debug( LDAP_DEBUG_ANY,
				"monitor_back_register_entry(\"%s\"): "
				"parent \"%s\" not found\n",
				e->e_name.bv_val, pdn.bv_val, 0 );
			return -1;
		}

260
261
		assert( e_parent->e_private != NULL );
		mp_parent = ( monitor_entry_t * )e_parent->e_private;
262

263
		if ( mp_parent->mp_flags & MONITOR_F_VOLATILE ) {
264
265
266
267
			/* entry is volatile; cannot append children */
			Debug( LDAP_DEBUG_ANY,
				"monitor_back_register_entry(\"%s\"): "
				"parent \"%s\" is volatile\n",
268
269
270
				e->e_name.bv_val, e_parent->e_name.bv_val, 0 );
			rc = -1;
			goto done;
271
272
273
274
275
276
		}

		mp = monitor_entrypriv_create();
		if ( mp == NULL ) {
			Debug( LDAP_DEBUG_ANY,
				"monitor_back_register_entry(\"%s\"): "
277
				"monitor_entrypriv_create() failed\n",
278
				e->e_name.bv_val, 0, 0 );
279
280
			rc = -1;
			goto done;
281
282
		}

283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
		e_new = entry_dup( e );
		if ( e == NULL ) {
			Debug( LDAP_DEBUG_ANY,
				"monitor_back_register_entry(\"%s\"): "
				"entry_dup() failed\n",
				e->e_name.bv_val, 0, 0 );
			rc = -1;
			goto done;
		}
		
		e_new->e_private = ( void * )mp;
		mp->mp_info = mp_parent->mp_info;
		mp->mp_flags = mp_parent->mp_flags | MONITOR_F_SUB;

		ep = &mp_parent->mp_children;
298
		for ( ; *ep; ) {
299
300
			mp_parent = ( monitor_entry_t * )(*ep)->e_private;
			ep = &mp_parent->mp_next;
301
		}
302
		*ep = e_new;
303

304
		if ( monitor_cache_add( mi, e_new ) ) {
305
306
307
308
			Debug( LDAP_DEBUG_ANY,
				"monitor_back_register_entry(\"%s\"): "
				"unable to add entry\n",
				e->e_name.bv_val, 0, 0 );
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
			rc = -1;
			goto done;
		}

done:;
		if ( rc ) {
			if ( mp ) {
				ch_free( mp );
			}
			if ( e_new ) {
				e_new->e_private = NULL;
				entry_free( e_new );
			}
		}

		if ( e_parent ) {
			monitor_cache_release( mi, e_parent );
326
327
328
		}

	} else {
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
		entry_limbo_t	*elp, el = { 0 };

		el.el_type = LIMBO_ENTRY;

		el.el_e = entry_dup( e );
		if ( el.el_e == NULL ) {
			Debug( LDAP_DEBUG_ANY,
				"monitor_back_register_entry(\"%s\"): "
				"entry_dup() failed\n",
				e->e_name.bv_val, 0, 0 );
			return -1;
		}
		
		el.el_cb = cb;

		elp = (entry_limbo_t *)ch_malloc( sizeof( entry_limbo_t ) );
		if ( elp ) {
			el.el_e->e_private = NULL;
			entry_free( el.el_e );
			return -1;
		}
350

351
352
353
354
355
356
357
		el.el_next = (entry_limbo_t *)mi->mi_entry_limbo;
		*elp = el;
		mi->mi_entry_limbo = (void *)elp;
	}

	return 0;
}
358

359
360
361
362
363
364
365
static int
monitor_filter2ndn_cb( Operation *op, SlapReply *rs )
{
	if ( rs->sr_type == REP_SEARCH ) {
		struct berval	*ndn = op->o_callback->sc_private;
		
		ber_dupbv( ndn, &rs->sr_entry->e_nname );
366
367
368
369
370
371
	}

	return 0;
}

int
372
373
374
375
monitor_filter2ndn( struct berval *base, int scope, struct berval *filter,
		struct berval *ndn )
{
	Connection	conn = { 0 };
376
377
	char opbuf[OPERATION_BUFFER_SIZE];
	Operation	*op;
378
379
	SlapReply	rs = { 0 };
	slap_callback	cb = { NULL, monitor_filter2ndn_cb, NULL, NULL };
Pierangelo Masarati's avatar
Pierangelo Masarati committed
380
	AttributeName	anlist[ 2 ];
381
382
383
384
385
386
387
388
	int		rc;

	BER_BVZERO( ndn );

	if ( be_monitor == NULL ) {
		return -1;
	}

389
390
	op = (Operation *)opbuf;
	connection_fake_init( &conn, op, &conn );
391

392
	op->o_tag = LDAP_REQ_SEARCH;
393
394

	/* use global malloc for now */
395
396
	op->o_tmpmemctx = NULL;
	op->o_tmpmfuncs = &ch_mfuncs;
397

398
	op->o_bd = be_monitor;
399
	if ( base == NULL || BER_BVISNULL( base ) ) {
400
401
402
403
		ber_dupbv_x( &op->o_req_dn, &op->o_bd->be_suffix[ 0 ],
				op->o_tmpmemctx );
		ber_dupbv_x( &op->o_req_ndn, &op->o_bd->be_nsuffix[ 0 ],
				op->o_tmpmemctx );
404
405

	} else {
406
407
		if ( dnPrettyNormal( NULL, base, &op->o_req_dn, &op->o_req_ndn,
					op->o_tmpmemctx ) ) {
408
409
410
411
			/* error */
		}
	}

412
	op->o_callback = &cb;
413
414
	cb.sc_private = (void *)ndn;

415
416
417
418
	op->ors_scope = scope;
	ber_dupbv_x( &op->ors_filterstr, filter, op->o_tmpmemctx );
	op->ors_filter = str2filter_x( op, filter->bv_val );
	op->ors_attrs = anlist;
419
	BER_BVSTR( &anlist[ 0 ].an_name, LDAP_NO_ATTRS );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
420
	BER_BVZERO( &anlist[ 1 ].an_name );
421
422
423
424
425
	op->ors_attrsonly = 0;
	op->ors_tlimit = SLAP_NO_LIMIT;
	op->ors_slimit = 1;
	op->ors_limit = NULL;
	op->ors_deref = LDAP_DEREF_NEVER;
426

427
428
	op->o_nocaching = 1;
	op->o_managedsait = SLAP_CONTROL_NONCRITICAL;
429

430
	rc = op->o_bd->be_search( op, &rs );
431

432
433
434
435
	filter_free_x( op, op->ors_filter );
	op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
	op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx );
	op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468

	if ( rc != 0 ) {
		return rc;
	}

	switch ( rs.sr_err ) {
	case LDAP_SUCCESS:
		if ( BER_BVISNULL( ndn ) ) {
			rc = -1;
		}
		break;
			
	case LDAP_SIZELIMIT_EXCEEDED:
	default:
		if ( !BER_BVISNULL( ndn ) ) {
			ber_memfree( ndn->bv_val );
			BER_BVZERO( ndn );
		}
		rc = -1;
		break;
	}

	return rc;
}

int
monitor_back_register_entry_attrs(
		struct berval		*ndn_in,
		Attribute		*a,
		monitor_callback_t	*cb,
		struct berval		*base,
		int			scope,
		struct berval		*filter )
469
470
{
	monitor_info_t 	*mi = ( monitor_info_t * )be_monitor->be_private;
471
	struct berval	ndn = BER_BVNULL;
472
473

	assert( mi != NULL );
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494

	if ( ndn_in != NULL ) {
		ndn = *ndn_in;
	}

	if ( a == NULL && cb == NULL ) {
		/* nothing to do */
		return -1;
	}

	if ( ( ndn_in == NULL || BER_BVISNULL( &ndn ) )
			&& BER_BVISNULL( filter ) )
	{
		/* need a filter */
		Debug( LDAP_DEBUG_ANY,
			"monitor_back_register_entry_*(\"\"): "
			"need a valid filter\n",
			0, 0, 0 );
		return -1;
	}

495
496
	if ( monitor_subsys_opened ) {
		Entry			*e = NULL;
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
		Attribute		**atp = NULL;
		monitor_entry_t 	*mp = NULL;
		monitor_callback_t	**mcp = NULL;
		int			rc = 0;
		int			freeit = 0;

		if ( BER_BVISNULL( &ndn ) ) {
			if ( monitor_filter2ndn( base, scope, filter, &ndn ) ) {
				/* entry does not exist */
				Debug( LDAP_DEBUG_ANY,
					"monitor_back_register_entry_*(\"\"): "
					"base=%s scope=%d filter=%s : "
					"unable to find entry\n",
					base->bv_val ? base->bv_val : "\"\"",
					scope, filter->bv_val );
				return -1;
			}

			freeit = 1;
		}
517

518
		if ( monitor_cache_get( mi, &ndn, &e ) != 0 ) {
519
520
			/* entry does not exist */
			Debug( LDAP_DEBUG_ANY,
521
				"monitor_back_register_entry_*(\"%s\"): "
522
				"entry does not exist\n",
523
524
525
				ndn.bv_val, 0, 0 );
			rc = -1;
			goto done;
526
527
528
529
530
531
532
533
		}

		assert( e->e_private != NULL );
		mp = ( monitor_entry_t * )e->e_private;

		if ( mp->mp_flags & MONITOR_F_VOLATILE ) {
			/* entry is volatile; cannot append callback */
			Debug( LDAP_DEBUG_ANY,
534
				"monitor_back_register_entry_*(\"%s\"): "
535
536
				"entry is volatile\n",
				e->e_name.bv_val, 0, 0 );
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
			rc = -1;
			goto done;
		}

		if ( a ) {
			for ( atp = &e->e_attrs; *atp; atp = &(*atp)->a_next )
				/* just get to last */ ;

			*atp = attrs_dup( a );
			if ( *atp == NULL ) {
				Debug( LDAP_DEBUG_ANY,
					"monitor_back_register_entry_*(\"%s\"): "
					"attrs_dup() failed\n",
					e->e_name.bv_val, 0, 0 );
				rc = -1;
				goto done;
			}
554
555
		}

556
557
558
		if ( cb ) {
			for ( mcp = &mp->mp_cb; *mcp; mcp = &(*mcp)->mc_next )
				/* go to tail */ ;
559
		
560
561
562
563
564
565
566
567
568
569
570
571
			/* NOTE: we do not clear cb->mc_next, so this function
			 * can be used to append a list of callbacks */
			(*mcp) = cb;
		}

done:;
		if ( rc ) {
			if ( *atp ) {
				attrs_free( *atp );
				*atp = NULL;
			}
		}
572

573
574
575
576
577
578
579
		if ( freeit ) {
			ber_memfree( ndn.bv_val );
		}

		if ( e ) {
			monitor_cache_release( mi, e );
		}
580
581

	} else {
582
		entry_limbo_t	*elp, el = { 0 };
583

584
585
586
587
588
589
590
591
592
593
594
595
596
597
		el.el_type = LIMBO_ATTRS;
		if ( !BER_BVISNULL( &ndn ) ) {
			ber_dupbv( &el.el_ndn, &ndn );
		}
		if ( !BER_BVISNULL( base ) ) {
			ber_dupbv( &el.el_base, base);
		}
		el.el_scope = scope;
		if ( !BER_BVISNULL( filter ) ) {
			ber_dupbv( &el.el_filter, filter );
		}

		el.el_a = attrs_dup( a );
		el.el_cb = cb;
598

599
600
601
602
603
604
605
606
607
		elp = (entry_limbo_t *)ch_malloc( sizeof( entry_limbo_t ) );
		if ( elp == NULL ) {
			attrs_free( a );
			return -1;
		}

		el.el_next = (entry_limbo_t *)mi->mi_entry_limbo;
		*elp = el;
		mi->mi_entry_limbo = (void *)elp;;
608
609
610
611
612
	}

	return 0;
}

613
614
615
616
617
618
619
620
621
622
623
624
int
monitor_back_register_entry_callback(
		struct berval		*ndn,
		monitor_callback_t	*cb,
		struct berval		*base,
		int			scope,
		struct berval		*filter )
{
	return monitor_back_register_entry_attrs( ndn, NULL, cb,
			base, scope, filter );
}

625
monitor_subsys_t *
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
monitor_back_get_subsys( const char *name )
{
	if ( monitor_subsys != NULL ) {
		int	i;
		
		for ( i = 0; monitor_subsys[ i ] != NULL; i++ ) {
			if ( strcasecmp( monitor_subsys[ i ]->mss_name, name ) == 0 ) {
				return monitor_subsys[ i ];
			}
		}
	}

	return NULL;
}

641
monitor_subsys_t *
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
monitor_back_get_subsys_by_dn( struct berval *ndn, int sub )
{
	if ( monitor_subsys != NULL ) {
		int	i;

		if ( sub ) {
			for ( i = 0; monitor_subsys[ i ] != NULL; i++ ) {
				if ( dnIsSuffix( ndn, &monitor_subsys[ i ]->mss_ndn ) ) {
					return monitor_subsys[ i ];
				}
			}

		} else {
			for ( i = 0; monitor_subsys[ i ] != NULL; i++ ) {
				if ( dn_match( ndn, &monitor_subsys[ i ]->mss_ndn ) ) {
					return monitor_subsys[ i ];
				}
			}
		}
	}

	return NULL;
}

666
667
668
669
670
int
monitor_back_initialize(
	BackendInfo	*bi
)
{
671
672
	monitor_subsys_t	*ms;
	static char		*controls[] = {
673
674
675
676
677
678
		LDAP_CONTROL_MANAGEDSAIT,
		NULL
	};

	bi->bi_controls = controls;

679
	bi->bi_init = 0;
680
	bi->bi_open = 0;
681
	bi->bi_config = monitor_back_config;
682
683
	bi->bi_close = 0;
	bi->bi_destroy = 0;
684
685
686

	bi->bi_db_init = monitor_back_db_init;
	bi->bi_db_config = monitor_back_db_config;
687
	bi->bi_db_open = monitor_back_db_open;
688
	bi->bi_db_close = 0;
689
690
	bi->bi_db_destroy = monitor_back_db_destroy;

691
	bi->bi_op_bind = monitor_back_bind;
692
	bi->bi_op_unbind = 0;
693
694
	bi->bi_op_search = monitor_back_search;
	bi->bi_op_compare = monitor_back_compare;
695
	bi->bi_op_modify = monitor_back_modify;
696
697
698
	bi->bi_op_modrdn = 0;
	bi->bi_op_add = 0;
	bi->bi_op_delete = 0;
Howard Chu's avatar
Howard Chu committed
699
	bi->bi_op_abandon = 0;
700

701
	bi->bi_extended = 0;
702

703
704
	bi->bi_entry_release_rw = 0;
	bi->bi_chk_referrals = 0;
705
	bi->bi_operational = monitor_back_operational;
706
707
708
709

	/*
	 * hooks for slap tools
	 */
710
711
712
713
714
715
716
717
	bi->bi_tool_entry_open = 0;
	bi->bi_tool_entry_close = 0;
	bi->bi_tool_entry_first = 0;
	bi->bi_tool_entry_next = 0;
	bi->bi_tool_entry_get = 0;
	bi->bi_tool_entry_put = 0;
	bi->bi_tool_entry_reindex = 0;
	bi->bi_tool_sync = 0;
718
719
720
	bi->bi_tool_dn2id_get = 0;
	bi->bi_tool_id2entry_get = 0;
	bi->bi_tool_entry_modify = 0;
721
722
723
724

	bi->bi_connection_init = 0;
	bi->bi_connection_destroy = 0;

725
726
727
728
729
730
	for ( ms = known_monitor_subsys; ms->mss_name != NULL; ms++ ) {
		if ( monitor_back_register_subsys( ms ) ) {
			return -1;
		}
	}

731
732
733
734
735
736
737
738
	return 0;
}

int
monitor_back_db_init(
	BackendDB	*be
)
{
739
740
741
742
743
	monitor_info_t 	*mi;
	int		i, rc;
	struct berval	dn, ndn;
	struct berval	bv;
	const char	*text;
744

745
746
747
	struct m_s {
		char	*name;
		char	*schema;
748
		slap_mask_t flags;
749
750
		int	offset;
	} moc[] = {
751
752
753
754
755
756
757
		{ "monitor", "( 1.3.6.1.4.1.4203.666.3.2 "
			"NAME 'monitor' "
			"DESC 'OpenLDAP system monitoring' "
			"SUP top STRUCTURAL "
			"MUST cn "
			"MAY ( "
				"description "
Pierangelo Masarati's avatar
Pierangelo Masarati committed
758
				"$ l "
759
#if 0	/* temporarily disabled */
Pierangelo Masarati's avatar
Pierangelo Masarati committed
760
761
762
763
				"$ st "
				"$ street "
				"$ postalAddress "
				"$ postalCode "
764
#endif
765
				"$ seeAlso "
766
				"$ labeledURI "
767
				"$ monitoredInfo "
Pierangelo Masarati's avatar
Pierangelo Masarati committed
768
				"$ managedInfo "
Pierangelo Masarati's avatar
Pierangelo Masarati committed
769
				"$ monitorOverlay "
770
			") )", SLAP_OC_OPERATIONAL|SLAP_OC_HIDE,
771
			offsetof(monitor_info_t, mi_oc_monitor) },
Kurt Zeilenga's avatar
Kurt Zeilenga committed
772
		{ "monitorServer", "( 1.3.6.1.4.1.4203.666.3.7 "
773
774
			"NAME 'monitorServer' "
			"DESC 'Server monitoring root entry' "
775
			"SUP monitor STRUCTURAL )", SLAP_OC_OPERATIONAL|SLAP_OC_HIDE,
776
			offsetof(monitor_info_t, mi_oc_monitorServer) },
Kurt Zeilenga's avatar
Kurt Zeilenga committed
777
		{ "monitorContainer", "( 1.3.6.1.4.1.4203.666.3.8 "
778
779
			"NAME 'monitorContainer' "
			"DESC 'monitor container class' "
780
			"SUP monitor STRUCTURAL )", SLAP_OC_OPERATIONAL|SLAP_OC_HIDE,
781
			offsetof(monitor_info_t, mi_oc_monitorContainer) },
782
783
		{ "monitorCounterObject", "( 1.3.6.1.4.1.4203.666.3.9 "
			"NAME 'monitorCounterObject' "
784
			"DESC 'monitor counter class' "
785
			"SUP monitor STRUCTURAL )", SLAP_OC_OPERATIONAL|SLAP_OC_HIDE,
786
			offsetof(monitor_info_t, mi_oc_monitorCounterObject) },
Kurt Zeilenga's avatar
Kurt Zeilenga committed
787
		{ "monitorOperation", "( 1.3.6.1.4.1.4203.666.3.10 "
788
789
			"NAME 'monitorOperation' "
			"DESC 'monitor operation class' "
790
			"SUP monitor STRUCTURAL )", SLAP_OC_OPERATIONAL|SLAP_OC_HIDE,
791
			offsetof(monitor_info_t, mi_oc_monitorOperation) },
Kurt Zeilenga's avatar
Kurt Zeilenga committed
792
		{ "monitorConnection", "( 1.3.6.1.4.1.4203.666.3.11 "
793
794
			"NAME 'monitorConnection' "
			"DESC 'monitor connection class' "
795
			"SUP monitor STRUCTURAL )", SLAP_OC_OPERATIONAL|SLAP_OC_HIDE,
796
			offsetof(monitor_info_t, mi_oc_monitorConnection) },
Kurt Zeilenga's avatar
Kurt Zeilenga committed
797
		{ "managedObject", "( 1.3.6.1.4.1.4203.666.3.12 "
798
799
			"NAME 'managedObject' "
			"DESC 'monitor managed entity class' "
800
			"SUP monitor STRUCTURAL )", SLAP_OC_OPERATIONAL|SLAP_OC_HIDE,
801
			offsetof(monitor_info_t, mi_oc_managedObject) },
802
		{ "monitoredObject", "( 1.3.6.1.4.1.4203.666.3.14 "
803
804
			"NAME 'monitoredObject' "
			"DESC 'monitor monitored entity class' "
805
			"SUP monitor STRUCTURAL )", SLAP_OC_OPERATIONAL|SLAP_OC_HIDE,
806
			offsetof(monitor_info_t, mi_oc_monitoredObject) },
807
		{ NULL, NULL, 0, -1 }
808
	}, mat[] = {
809
		{ "monitoredInfo", "( 1.3.6.1.4.1.4203.666.1.14 "
810
811
			"NAME 'monitoredInfo' "
			"DESC 'monitored info' "
812
813
814
815
816
			/* "SUP name " */
			"EQUALITY caseIgnoreMatch "
			"SUBSTR caseIgnoreSubstringsMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} "
			"NO-USER-MODIFICATION "
817
			"USAGE directoryOperation )", SLAP_AT_HIDE,
818
			offsetof(monitor_info_t, mi_ad_monitoredInfo) },
Kurt Zeilenga's avatar
Kurt Zeilenga committed
819
		{ "managedInfo", "( 1.3.6.1.4.1.4203.666.1.15 "
820
821
			"NAME 'managedInfo' "
			"DESC 'monitor managed info' "
822
			"SUP name )", SLAP_AT_HIDE,
823
			offsetof(monitor_info_t, mi_ad_managedInfo) },
Kurt Zeilenga's avatar
Kurt Zeilenga committed
824
		{ "monitorCounter", "( 1.3.6.1.4.1.4203.666.1.16 "
825
826
827
			"NAME 'monitorCounter' "
			"DESC 'monitor counter' "
			"EQUALITY integerMatch "
Kurt Zeilenga's avatar
Kurt Zeilenga committed
828
			"ORDERING integerOrderingMatch "
Pierangelo Masarati's avatar
Pierangelo Masarati committed
829
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 "
830
			"NO-USER-MODIFICATION "
831
			"USAGE directoryOperation )", SLAP_AT_HIDE,
832
			offsetof(monitor_info_t, mi_ad_monitorCounter) },
Kurt Zeilenga's avatar
Kurt Zeilenga committed
833
		{ "monitorOpCompleted", "( 1.3.6.1.4.1.4203.666.1.17 "
834
835
			"NAME 'monitorOpCompleted' "
			"DESC 'monitor completed operations' "
836
837
			"SUP monitorCounter "
			"NO-USER-MODIFICATION "
838
			"USAGE directoryOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
839
			offsetof(monitor_info_t, mi_ad_monitorOpCompleted) },
Kurt Zeilenga's avatar
Kurt Zeilenga committed
840
		{ "monitorOpInitiated", "( 1.3.6.1.4.1.4203.666.1.18 "
841
842
			"NAME 'monitorOpInitiated' "
			"DESC 'monitor initiated operations' "
843
844
			"SUP monitorCounter "
			"NO-USER-MODIFICATION "
845
			"USAGE directoryOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
846
			offsetof(monitor_info_t, mi_ad_monitorOpInitiated) },
Kurt Zeilenga's avatar
Kurt Zeilenga committed
847
		{ "monitorConnectionNumber", "( 1.3.6.1.4.1.4203.666.1.19 "
848
849
			"NAME 'monitorConnectionNumber' "
			"DESC 'monitor connection number' "
850
851
			"SUP monitorCounter "
			"NO-USER-MODIFICATION "
852
			"USAGE directoryOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
853
			offsetof(monitor_info_t, mi_ad_monitorConnectionNumber) },
Kurt Zeilenga's avatar
Kurt Zeilenga committed
854
		{ "monitorConnectionAuthzDN", "( 1.3.6.1.4.1.4203.666.1.20 "
855
856
			"NAME 'monitorConnectionAuthzDN' "
			"DESC 'monitor connection authorization DN' "
857
858
859
860
			/* "SUP distinguishedName " */
			"EQUALITY distinguishedNameMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 "
			"NO-USER-MODIFICATION "
861
			"USAGE directoryOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
862
			offsetof(monitor_info_t, mi_ad_monitorConnectionAuthzDN) },
Kurt Zeilenga's avatar
Kurt Zeilenga committed
863
		{ "monitorConnectionLocalAddress", "( 1.3.6.1.4.1.4203.666.1.21 "
864
865
			"NAME 'monitorConnectionLocalAddress' "
			"DESC 'monitor connection local address' "
866
867
			"SUP monitoredInfo "
			"NO-USER-MODIFICATION "
868
			"USAGE directoryOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
869
			offsetof(monitor_info_t, mi_ad_monitorConnectionLocalAddress) },
Kurt Zeilenga's avatar
Kurt Zeilenga committed
870
		{ "monitorConnectionPeerAddress", "( 1.3.6.1.4.1.4203.666.1.22 "
871
872
			"NAME 'monitorConnectionPeerAddress' "
			"DESC 'monitor connection peer address' "
873
874
			"SUP monitoredInfo "
			"NO-USER-MODIFICATION "
875
			"USAGE directoryOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
876
			offsetof(monitor_info_t, mi_ad_monitorConnectionPeerAddress) },
877
878
879
880
881
882
		{ "monitorTimestamp", "( 1.3.6.1.4.1.4203.666.1.24 "
			"NAME 'monitorTimestamp' "
			"DESC 'monitor timestamp' "
			"EQUALITY generalizedTimeMatch "
			"ORDERING generalizedTimeOrderingMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 "
Kurt Zeilenga's avatar
Kurt Zeilenga committed
883
			"SINGLE-VALUE "
884
			"NO-USER-MODIFICATION "
885
			"USAGE directoryOperation )", SLAP_AT_FINAL|SLAP_AT_HIDE,
886
			offsetof(monitor_info_t, mi_ad_monitorTimestamp) },
Pierangelo Masarati's avatar
Pierangelo Masarati committed
887
888
889
890
891
892
		{ "monitorOverlay", "( 1.3.6.1.4.1.4203.666.1.27 "
			"NAME 'monitorOverlay' "
			"DESC 'name of overlays defined for a give database' "
			"SUP monitoredInfo "
			"NO-USER-MODIFICATION "
			"USAGE directoryOperation )", SLAP_AT_HIDE,
893
			offsetof(monitor_info_t, mi_ad_monitorOverlay) },
894
895
896
897
898
899
900
		{ "readOnly", "( 1.3.6.1.4.1.4203.666.1.31 "
			"NAME 'readOnly' "
			"DESC 'read/write status of a given database' "
			"EQUALITY booleanMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 "
			"SINGLE-VALUE "
			"USAGE directoryOperation )", SLAP_AT_HIDE,
901
			offsetof(monitor_info_t, mi_ad_readOnly) },
902
903
904
905
		{ "restrictedOperation", "( 1.3.6.1.4.1.4203.666.1.32 "
			"NAME 'restrictedOperation' "
			"DESC 'name of restricted operation for a given database' "
			"SUP managedInfo )", SLAP_AT_HIDE,
906
			offsetof(monitor_info_t, mi_ad_restrictedOperation ) },
907
#ifdef INTEGRATE_CORE_SCHEMA
908
909
910
		{ NULL, NULL, 0, -1 },	/* description */
		{ NULL, NULL, 0, -1 },	/* seeAlso */
		{ NULL, NULL, 0, -1 },	/* l */
911
		{ NULL, NULL, 0, -1 },	/* labeledURI */
912
#endif /* INTEGRATE_CORE_SCHEMA */
913
		{ NULL, NULL, 0, -1 }
914
915
916
917
918
919
	}, mat_core[] = {
		{ "description", "( 2.5.4.13 "
			"NAME 'description' "
			"DESC 'RFC2256: descriptive information' "
			"EQUALITY caseIgnoreMatch "
			"SUBSTR caseIgnoreSubstringsMatch "
920
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{1024} )", 0,
921
			offsetof(monitor_info_t, mi_ad_description) },
922
923
924
		{ "seeAlso", "( 2.5.4.34 "
			"NAME 'seeAlso' "
			"DESC 'RFC2256: DN of related object' "
925
			"SUP distinguishedName )", 0,
926
			offsetof(monitor_info_t, mi_ad_seeAlso) },
927
928
929
		{ "l", "( 2.5.4.7 "
			"NAME ( 'l' 'localityName' ) "
			"DESC 'RFC2256: locality which this object resides in' "
930
			"SUP name )", 0,
931
			offsetof(monitor_info_t, mi_ad_l) },
Pierangelo Masarati's avatar
Pierangelo Masarati committed
932
#ifdef MONITOR_DEFINE_LABELEDURI
933
934
935
936
937
		{ "labeledURI", "( 1.3.6.1.4.1.250.1.57 "
			"NAME 'labeledURI' "
			"DESC 'RFC2079: Uniform Resource Identifier with optional label' "
			"EQUALITY caseExactMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", 0,
938
			offsetof(monitor_info_t, mi_ad_labeledURI) },
Pierangelo Masarati's avatar
Pierangelo Masarati committed
939
#endif /* MONITOR_DEFINE_LABELEDURI */
940
		{ NULL, NULL, 0, -1 }
941
	};
942
	
943
	/*
944
	 * database monitor can be defined once only
945
	 */
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
	if ( be_monitor ) {
		Debug( LDAP_DEBUG_ANY,
			"only one monitor backend is allowed\n", 0, 0, 0 );
		return( -1 );
	}
	be_monitor = be;

	/* indicate system schema supported */
	SLAP_BFLAGS(be) |= SLAP_BFLAG_MONITOR;

	dn.bv_val = SLAPD_MONITOR_DN;
	dn.bv_len = sizeof( SLAPD_MONITOR_DN ) - 1;

	rc = dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL );
	if( rc != LDAP_SUCCESS ) {
		Debug( LDAP_DEBUG_ANY,
			"unable to normalize monitor DN \"%s\"\n",
			SLAPD_MONITOR_DN, 0, 0 );
		return -1;
	}
966

967
968
969
	ber_dupbv( &bv, &dn );
	ber_bvarray_add( &be->be_suffix, &bv );
	ber_bvarray_add( &be->be_nsuffix, &ndn );
970

971
	mi = ( monitor_info_t * )ch_calloc( sizeof( monitor_info_t ), 1 );
972
973
974
975
976
977
	if ( mi == NULL ) {
		Debug( LDAP_DEBUG_ANY,
			"unable to initialize monitor backend\n", 0, 0, 0 );
		return -1;
	}

978
	memset( mi, 0, sizeof( monitor_info_t ) );
979
980
981
982
983

	ldap_pvt_thread_mutex_init( &mi->mi_cache_mutex );

	be->be_private = mi;
	
984
#ifdef INTEGRATE_CORE_SCHEMA
985
	/* prepare for schema integration */
986
	for ( k = 0; mat[ k ].name != NULL; k++ );
987
#endif /* INTEGRATE_CORE_SCHEMA */
988

989
	for ( i = 0; mat_core[ i ].name != NULL; i++ ) {
990
991
992
		AttributeDescription	**ad;
		const char		*text;

993
994
		ad = ((AttributeDescription **)&(((char *)mi)[ mat_core[ i ].offset ]));
		ad[ 0 ] = NULL;
995

996
		switch (slap_str2ad( mat_core[ i ].name, ad, &text ) ) {
997
998
999
1000
1001
		case LDAP_SUCCESS:
			break;

#ifdef INTEGRATE_CORE_SCHEMA
		case LDAP_UNDEFINED_TYPE:
1002
			mat[ k ] = mat_core[ i ];
1003
1004
1005
1006
1007
1008
1009
			k++;
			break;
#endif /* INTEGRATE_CORE_SCHEMA */

		default:
			Debug( LDAP_DEBUG_ANY,
				"monitor_back_db_init: %s: %s\n",
1010
				mat_core[ i ].name, text, 0 );
1011
1012
1013
1014
1015
			return( -1 );
		}
	}

	/* schema integration */
1016
	for ( i = 0; mat[ i ].name; i++ ) {
1017
1018
1019
1020
		LDAPAttributeType	*at;
		int			code;
		const char		*err;
		AttributeDescription	**ad;
1021

1022
		at = ldap_str2attributetype( mat[ i ].schema, &code,
1023
			&err, LDAP_SCHEMA_ALLOW_ALL );
1024
1025
		if ( !at ) {
			Debug( LDAP_DEBUG_ANY, "monitor_back_db_init: "
1026
				"in AttributeType \"%s\" %s before %s\n",
1027
				mat[ i ].name, ldap_scherr2str(code), err );
1028
1029
			return -1;
		}
1030

1031
1032
		if ( at->at_oid == NULL ) {
			Debug( LDAP_DEBUG_ANY, "monitor_back_db_init: "
1033
				"null OID for attributeType \"%s\"\n",
1034
				mat[ i ].name, 0, 0 );
1035
1036
			return -1;
		}
1037

1038
1039
1040
		code = at_add(at, &err);
		if ( code ) {
			Debug( LDAP_DEBUG_ANY, "monitor_back_db_init: "
1041
				"%s in attributeType \"%s\"\n",
1042
				scherr2str(code), mat[ i ].name, 0 );
1043
1044
1045
			return -1;
		}
		ldap_memfree(at);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1046

1047
1048
1049
		ad = ((AttributeDescription **)&(((char *)mi)[ mat[ i ].offset ]));
		ad[ 0 ] = NULL;
		if ( slap_str2ad( mat[ i ].name, ad, &text ) ) {
1050
1051
1052
1053
			Debug( LDAP_DEBUG_ANY,
				"monitor_back_db_init: %s\n", text, 0, 0 );
			return -1;
		}
1054

1055
		(*ad)->ad_type->sat_flags |= mat[ i ].flags;
1056
1057
	}

1058
	for ( i = 0; moc[ i ].name; i++ ) {
1059
1060
1061
1062
1063
		LDAPObjectClass		*oc;
		int			code;
		const char		*err;
		ObjectClass		*Oc;

1064
		oc = ldap_str2objectclass(moc[ i ].schema, &code, &err,
1065
1066
1067
				LDAP_SCHEMA_ALLOW_ALL );
		if ( !oc ) {
			Debug( LDAP_DEBUG_ANY,
1068
				"unable to parse monitor objectclass \"%s\": "
1069
				"%s before %s\n" , moc[ i ].name,
1070
1071
1072
1073
1074
1075
				ldap_scherr2str(code), err );
			return -1;
		}

		if ( oc->oc_oid == NULL ) {
			Debug( LDAP_DEBUG_ANY,
1076
				"objectclass \"%s\" has no OID\n" ,
1077
				moc[ i ].name, 0, 0 );
1078
1079
1080
			return -1;
		}

1081
		code = oc_add(oc, 0, &err);
1082
1083
		if ( code ) {
			Debug( LDAP_DEBUG_ANY,
1084
				"objectclass \"%s\": %s \"%s\"\n" ,
1085
				moc[ i ].name, scherr2str(code), err );
1086
1087
1088
1089
1090
			return -1;
		}

		ldap_memfree(oc);

1091
		Oc = oc_find( moc[ i ].name );
1092
		if ( Oc == NULL ) {
1093
			Debug( LDAP_DEBUG_ANY, "monitor_back_db_init: "
1094
					"unable to find objectClass %s "
1095
					"(just added)\n", moc[ i ].name, 0, 0 );
1096
			return -1;
1097
1098
		}

1099
		Oc->soc_flags |= moc[ i ].flags;
1100

1101
		((ObjectClass **)&(((char *)mi)[ moc[ i ].offset ]))[ 0 ] = Oc;
1102
	}