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