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