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