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