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 */ 49BackendDB *be_monitor; 50 51static struct monitor_subsys_t **monitor_subsys; 52static int monitor_subsys_opened; 53static monitor_info_t monitor_info; 54static 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 */ 90static 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 238int 239monitor_subsys_is_opened( void ) 240{ 241 return monitor_subsys_opened; 242} 243 244int 245monitor_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 284enum { 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 298typedef 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 315int 316monitor_back_is_configured( void ) 317{ 318 return be_monitor != NULL; 319} 320 321int 322monitor_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 360int 361monitor_back_register_backend( 362 BackendInfo *bi ) 363{ 364 return -1; 365} 366 367int 368monitor_back_register_overlay_info( 369 slap_overinst *on ) 370{ 371 return -1; 372} 373 374int 375monitor_back_register_backend_limbo( 376 BackendInfo *bi ) 377{ 378 return -1; 379} 380 381int 382monitor_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 417int 418monitor_back_register_overlay_info_limbo( 419 slap_overinst *on ) 420{ 421 return -1; 422} 423 424int 425monitor_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 462int 463monitor_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 574done:; 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 626int 627monitor_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 774done:; 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 830done_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 850static int 851monitor_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 869int 870monitor_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 941cleanup:; 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 979int 980monitor_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 1111done:; 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 1169int 1170monitor_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 */ 1186int 1187monitor_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 1284int 1285monitor_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 1426int 1427monitor_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 1598int 1599monitor_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 1613monitor_subsys_t * 1614monitor_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 1629monitor_subsys_t * 1630monitor_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 1656int 1657monitor_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 2114int 2115monitor_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 2188static void 2189monitor_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 2223int 2224monitor_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 2490int 2491monitor_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 2505int 2506monitor_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 2522int 2523monitor_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