1/* conn.c - deal with connection subsystem */ 2/* $OpenLDAP$ */ 3/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 4 * 5 * Copyright 2001-2011 The OpenLDAP Foundation. 6 * Portions Copyright 2001-2003 Pierangelo Masarati. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted only as authorized by the OpenLDAP 11 * Public License. 12 * 13 * A copy of this license is available in file LICENSE in the 14 * top-level directory of the distribution or, alternatively, at 15 * <http://www.OpenLDAP.org/license.html>. 16 */ 17/* ACKNOWLEDGEMENTS: 18 * This work was initially developed by Pierangelo Masarati for inclusion 19 * in OpenLDAP Software. 20 */ 21 22#include "portable.h" 23 24#include <stdio.h> 25#include <ac/string.h> 26 27#include "slap.h" 28#include "lutil.h" 29#include "back-monitor.h" 30 31static int 32monitor_subsys_conn_update( 33 Operation *op, 34 SlapReply *rs, 35 Entry *e ); 36 37static int 38monitor_subsys_conn_create( 39 Operation *op, 40 SlapReply *rs, 41 struct berval *ndn, 42 Entry *e_parent, 43 Entry **ep ); 44 45int 46monitor_subsys_conn_init( 47 BackendDB *be, 48 monitor_subsys_t *ms ) 49{ 50 monitor_info_t *mi; 51 Entry *e, **ep, *e_conn; 52 monitor_entry_t *mp; 53 char buf[ BACKMONITOR_BUFSIZE ]; 54 struct berval bv; 55 56 assert( be != NULL ); 57 58 ms->mss_update = monitor_subsys_conn_update; 59 ms->mss_create = monitor_subsys_conn_create; 60 61 mi = ( monitor_info_t * )be->be_private; 62 63 if ( monitor_cache_get( mi, &ms->mss_ndn, &e_conn ) ) { 64 Debug( LDAP_DEBUG_ANY, 65 "monitor_subsys_conn_init: " 66 "unable to get entry \"%s\"\n", 67 ms->mss_ndn.bv_val, 0, 0 ); 68 return( -1 ); 69 } 70 71 mp = ( monitor_entry_t * )e_conn->e_private; 72 mp->mp_children = NULL; 73 ep = &mp->mp_children; 74 75 /* 76 * Max file descriptors 77 */ 78 BER_BVSTR( &bv, "cn=Max File Descriptors" ); 79 e = monitor_entry_stub( &ms->mss_dn, &ms->mss_ndn, &bv, 80 mi->mi_oc_monitorCounterObject, mi, NULL, NULL ); 81 82 if ( e == NULL ) { 83 Debug( LDAP_DEBUG_ANY, 84 "monitor_subsys_conn_init: " 85 "unable to create entry \"%s,%s\"\n", 86 bv.bv_val, ms->mss_ndn.bv_val, 0 ); 87 return( -1 ); 88 } 89 90 if ( dtblsize ) { 91 bv.bv_val = buf; 92 bv.bv_len = snprintf( buf, sizeof( buf ), "%d", dtblsize ); 93 94 } else { 95 BER_BVSTR( &bv, "0" ); 96 } 97 attr_merge_one( e, mi->mi_ad_monitorCounter, &bv, NULL ); 98 99 mp = monitor_entrypriv_create(); 100 if ( mp == NULL ) { 101 return -1; 102 } 103 e->e_private = ( void * )mp; 104 mp->mp_info = ms; 105 mp->mp_flags = ms->mss_flags \ 106 | MONITOR_F_SUB | MONITOR_F_PERSISTENT; 107 mp->mp_flags &= ~MONITOR_F_VOLATILE_CH; 108 109 if ( monitor_cache_add( mi, e ) ) { 110 Debug( LDAP_DEBUG_ANY, 111 "monitor_subsys_conn_init: " 112 "unable to add entry \"cn=Total,%s\"\n", 113 ms->mss_ndn.bv_val, 0, 0 ); 114 return( -1 ); 115 } 116 117 *ep = e; 118 ep = &mp->mp_next; 119 120 /* 121 * Total conns 122 */ 123 BER_BVSTR( &bv, "cn=Total" ); 124 e = monitor_entry_stub( &ms->mss_dn, &ms->mss_ndn, &bv, 125 mi->mi_oc_monitorCounterObject, mi, NULL, NULL ); 126 127 if ( e == NULL ) { 128 Debug( LDAP_DEBUG_ANY, 129 "monitor_subsys_conn_init: " 130 "unable to create entry \"cn=Total,%s\"\n", 131 ms->mss_ndn.bv_val, 0, 0 ); 132 return( -1 ); 133 } 134 135 BER_BVSTR( &bv, "-1" ); 136 attr_merge_one( e, mi->mi_ad_monitorCounter, &bv, NULL ); 137 138 mp = monitor_entrypriv_create(); 139 if ( mp == NULL ) { 140 return -1; 141 } 142 e->e_private = ( void * )mp; 143 mp->mp_info = ms; 144 mp->mp_flags = ms->mss_flags \ 145 | MONITOR_F_SUB | MONITOR_F_PERSISTENT; 146 mp->mp_flags &= ~MONITOR_F_VOLATILE_CH; 147 148 if ( monitor_cache_add( mi, e ) ) { 149 Debug( LDAP_DEBUG_ANY, 150 "monitor_subsys_conn_init: " 151 "unable to add entry \"cn=Total,%s\"\n", 152 ms->mss_ndn.bv_val, 0, 0 ); 153 return( -1 ); 154 } 155 156 *ep = e; 157 ep = &mp->mp_next; 158 159 /* 160 * Current conns 161 */ 162 BER_BVSTR( &bv, "cn=Current" ); 163 e = monitor_entry_stub( &ms->mss_dn, &ms->mss_ndn, &bv, 164 mi->mi_oc_monitorCounterObject, mi, NULL, NULL ); 165 166 if ( e == NULL ) { 167 Debug( LDAP_DEBUG_ANY, 168 "monitor_subsys_conn_init: " 169 "unable to create entry \"cn=Current,%s\"\n", 170 ms->mss_ndn.bv_val, 0, 0 ); 171 return( -1 ); 172 } 173 174 BER_BVSTR( &bv, "0" ); 175 attr_merge_one( e, mi->mi_ad_monitorCounter, &bv, NULL ); 176 177 mp = monitor_entrypriv_create(); 178 if ( mp == NULL ) { 179 return -1; 180 } 181 e->e_private = ( void * )mp; 182 mp->mp_info = ms; 183 mp->mp_flags = ms->mss_flags \ 184 | MONITOR_F_SUB | MONITOR_F_PERSISTENT; 185 mp->mp_flags &= ~MONITOR_F_VOLATILE_CH; 186 187 if ( monitor_cache_add( mi, e ) ) { 188 Debug( LDAP_DEBUG_ANY, 189 "monitor_subsys_conn_init: " 190 "unable to add entry \"cn=Current,%s\"\n", 191 ms->mss_ndn.bv_val, 0, 0 ); 192 return( -1 ); 193 } 194 195 *ep = e; 196 ep = &mp->mp_next; 197 198 monitor_cache_release( mi, e_conn ); 199 200 return( 0 ); 201} 202 203static int 204monitor_subsys_conn_update( 205 Operation *op, 206 SlapReply *rs, 207 Entry *e ) 208{ 209 monitor_info_t *mi = ( monitor_info_t * )op->o_bd->be_private; 210 211 long n = -1; 212 static struct berval total_bv = BER_BVC( "cn=total" ), 213 current_bv = BER_BVC( "cn=current" ); 214 struct berval rdn; 215 216 assert( mi != NULL ); 217 assert( e != NULL ); 218 219 dnRdn( &e->e_nname, &rdn ); 220 221 if ( dn_match( &rdn, &total_bv ) ) { 222 n = connections_nextid(); 223 224 } else if ( dn_match( &rdn, ¤t_bv ) ) { 225 Connection *c; 226 int connindex; 227 228 for ( n = 0, c = connection_first( &connindex ); 229 c != NULL; 230 n++, c = connection_next( c, &connindex ) ) 231 { 232 /* No Op */ ; 233 } 234 connection_done( c ); 235 } 236 237 if ( n != -1 ) { 238 Attribute *a; 239 char buf[LDAP_PVT_INTTYPE_CHARS(long)]; 240 ber_len_t len; 241 242 a = attr_find( e->e_attrs, mi->mi_ad_monitorCounter ); 243 if ( a == NULL ) { 244 return( -1 ); 245 } 246 247 snprintf( buf, sizeof( buf ), "%ld", n ); 248 len = strlen( buf ); 249 if ( len > a->a_vals[ 0 ].bv_len ) { 250 a->a_vals[ 0 ].bv_val = ber_memrealloc( a->a_vals[ 0 ].bv_val, len + 1 ); 251 } 252 a->a_vals[ 0 ].bv_len = len; 253 AC_MEMCPY( a->a_vals[ 0 ].bv_val, buf, len + 1 ); 254 255 /* FIXME: touch modifyTimestamp? */ 256 } 257 258 return SLAP_CB_CONTINUE; 259} 260 261static int 262conn_create( 263 monitor_info_t *mi, 264 Connection *c, 265 Entry **ep, 266 monitor_subsys_t *ms ) 267{ 268 monitor_entry_t *mp; 269 struct tm tm; 270 char buf[ BACKMONITOR_BUFSIZE ]; 271 char buf2[ LDAP_LUTIL_GENTIME_BUFSIZE ]; 272 char buf3[ LDAP_LUTIL_GENTIME_BUFSIZE ]; 273 274 struct berval bv, ctmbv, mtmbv; 275 struct berval bv_unknown= BER_BVC("unknown"); 276 277 Entry *e; 278 279 assert( c != NULL ); 280 assert( ep != NULL ); 281 282 ldap_pvt_gmtime( &c->c_starttime, &tm ); 283 284 ctmbv.bv_len = lutil_gentime( buf2, sizeof( buf2 ), &tm ); 285 ctmbv.bv_val = buf2; 286 287 ldap_pvt_gmtime( &c->c_activitytime, &tm ); 288 mtmbv.bv_len = lutil_gentime( buf3, sizeof( buf3 ), &tm ); 289 mtmbv.bv_val = buf3; 290 291 bv.bv_len = snprintf( buf, sizeof( buf ), 292 "cn=Connection %ld", c->c_connid ); 293 bv.bv_val = buf; 294 e = monitor_entry_stub( &ms->mss_dn, &ms->mss_ndn, &bv, 295 mi->mi_oc_monitorConnection, mi, &ctmbv, &mtmbv ); 296 297 if ( e == NULL) { 298 Debug( LDAP_DEBUG_ANY, 299 "monitor_subsys_conn_create: " 300 "unable to create entry " 301 "\"cn=Connection %ld,%s\"\n", 302 c->c_connid, 303 ms->mss_dn.bv_val, 0 ); 304 return( -1 ); 305 } 306 307#ifdef MONITOR_LEGACY_CONN 308 /* NOTE: this will disappear, as the exploded data 309 * has been moved to dedicated attributes */ 310 bv.bv_len = snprintf( buf, sizeof( buf ), 311 "%ld " 312 ": %ld " 313 ": %ld/%ld/%ld/%ld " 314 ": %ld/%ld/%ld " 315 ": %s%s%s%s%s%s " 316 ": %s " 317 ": %s " 318 ": %s " 319 ": %s " 320 ": %s " 321 ": %s " 322 ": %s", 323 c->c_connid, 324 (long) c->c_protocol, 325 c->c_n_ops_received, c->c_n_ops_executing, 326 c->c_n_ops_pending, c->c_n_ops_completed, 327 328 /* add low-level counters here */ 329 c->c_n_get, c->c_n_read, c->c_n_write, 330 331 c->c_currentber ? "r" : "", 332 c->c_writewaiter ? "w" : "", 333 LDAP_STAILQ_EMPTY( &c->c_ops ) ? "" : "x", 334 LDAP_STAILQ_EMPTY( &c->c_pending_ops ) ? "" : "p", 335 connection_state2str( c->c_conn_state ), 336 c->c_sasl_bind_in_progress ? "S" : "", 337 338 c->c_dn.bv_len ? c->c_dn.bv_val : SLAPD_ANONYMOUS, 339 340 c->c_listener_url.bv_val, 341 BER_BVISNULL( &c->c_peer_domain ) 342 ? "" : c->c_peer_domain.bv_val, 343 BER_BVISNULL( &c->c_peer_name ) 344 ? "" : c->c_peer_name.bv_val, 345 c->c_sock_name.bv_val, 346 347 buf2, 348 buf3 ); 349 attr_merge_normalize_one( e, mi->mi_ad_monitoredInfo, &bv, NULL ); 350#endif /* MONITOR_LEGACY_CONN */ 351 352 bv.bv_len = snprintf( buf, sizeof( buf ), "%lu", c->c_connid ); 353 attr_merge_one( e, mi->mi_ad_monitorConnectionNumber, &bv, NULL ); 354 355 bv.bv_len = snprintf( buf, sizeof( buf ), "%ld", (long) c->c_protocol ); 356 attr_merge_normalize_one( e, mi->mi_ad_monitorConnectionProtocol, &bv, NULL ); 357 358 bv.bv_len = snprintf( buf, sizeof( buf ), "%ld", c->c_n_ops_received ); 359 attr_merge_one( e, mi->mi_ad_monitorConnectionOpsReceived, &bv, NULL ); 360 361 bv.bv_len = snprintf( buf, sizeof( buf ), "%ld", c->c_n_ops_executing ); 362 attr_merge_one( e, mi->mi_ad_monitorConnectionOpsExecuting, &bv, NULL ); 363 364 bv.bv_len = snprintf( buf, sizeof( buf ), "%ld", c->c_n_ops_pending ); 365 attr_merge_one( e, mi->mi_ad_monitorConnectionOpsPending, &bv, NULL ); 366 367 bv.bv_len = snprintf( buf, sizeof( buf ), "%ld", c->c_n_ops_completed ); 368 attr_merge_one( e, mi->mi_ad_monitorConnectionOpsCompleted, &bv, NULL ); 369 370 bv.bv_len = snprintf( buf, sizeof( buf ), "%ld", c->c_n_get ); 371 attr_merge_one( e, mi->mi_ad_monitorConnectionGet, &bv, NULL ); 372 373 bv.bv_len = snprintf( buf, sizeof( buf ), "%ld", c->c_n_read ); 374 attr_merge_one( e, mi->mi_ad_monitorConnectionRead, &bv, NULL ); 375 376 bv.bv_len = snprintf( buf, sizeof( buf ), "%ld", c->c_n_write ); 377 attr_merge_one( e, mi->mi_ad_monitorConnectionWrite, &bv, NULL ); 378 379 bv.bv_len = snprintf( buf, sizeof( buf ), "%s%s%s%s%s%s", 380 c->c_currentber ? "r" : "", 381 c->c_writewaiter ? "w" : "", 382 LDAP_STAILQ_EMPTY( &c->c_ops ) ? "" : "x", 383 LDAP_STAILQ_EMPTY( &c->c_pending_ops ) ? "" : "p", 384 connection_state2str( c->c_conn_state ), 385 c->c_sasl_bind_in_progress ? "S" : "" ); 386 attr_merge_normalize_one( e, mi->mi_ad_monitorConnectionMask, &bv, NULL ); 387 388 attr_merge_one( e, mi->mi_ad_monitorConnectionAuthzDN, 389 &c->c_dn, &c->c_ndn ); 390 391 /* NOTE: client connections leave the c_peer_* fields NULL */ 392 assert( !BER_BVISNULL( &c->c_listener_url ) ); 393 attr_merge_normalize_one( e, mi->mi_ad_monitorConnectionListener, 394 &c->c_listener_url, NULL ); 395 396 attr_merge_normalize_one( e, mi->mi_ad_monitorConnectionPeerDomain, 397 BER_BVISNULL( &c->c_peer_domain ) ? &bv_unknown : &c->c_peer_domain, 398 NULL ); 399 400 attr_merge_normalize_one( e, mi->mi_ad_monitorConnectionPeerAddress, 401 BER_BVISNULL( &c->c_peer_name ) ? &bv_unknown : &c->c_peer_name, 402 NULL ); 403 404 assert( !BER_BVISNULL( &c->c_sock_name ) ); 405 attr_merge_normalize_one( e, mi->mi_ad_monitorConnectionLocalAddress, 406 &c->c_sock_name, NULL ); 407 408 attr_merge_normalize_one( e, mi->mi_ad_monitorConnectionStartTime, &ctmbv, NULL ); 409 410 attr_merge_normalize_one( e, mi->mi_ad_monitorConnectionActivityTime, &mtmbv, NULL ); 411 412 mp = monitor_entrypriv_create(); 413 if ( mp == NULL ) { 414 return LDAP_OTHER; 415 } 416 e->e_private = ( void * )mp; 417 mp->mp_info = ms; 418 mp->mp_flags = MONITOR_F_SUB | MONITOR_F_VOLATILE; 419 420 *ep = e; 421 422 return SLAP_CB_CONTINUE; 423} 424 425static int 426monitor_subsys_conn_create( 427 Operation *op, 428 SlapReply *rs, 429 struct berval *ndn, 430 Entry *e_parent, 431 Entry **ep ) 432{ 433 monitor_info_t *mi = ( monitor_info_t * )op->o_bd->be_private; 434 435 int rc = SLAP_CB_CONTINUE; 436 monitor_subsys_t *ms; 437 438 assert( mi != NULL ); 439 assert( e_parent != NULL ); 440 assert( ep != NULL ); 441 442 ms = (( monitor_entry_t *)e_parent->e_private)->mp_info; 443 444 *ep = NULL; 445 446 if ( ndn == NULL ) { 447 Connection *c; 448 int connindex; 449 Entry *e = NULL, 450 *e_tmp = NULL; 451 452 /* create all the children of e_parent */ 453 for ( c = connection_first( &connindex ); 454 c != NULL; 455 c = connection_next( c, &connindex ) ) 456 { 457 monitor_entry_t *mp; 458 459 if ( conn_create( mi, c, &e, ms ) != SLAP_CB_CONTINUE 460 || e == NULL ) 461 { 462 for ( ; e_tmp != NULL; ) { 463 mp = ( monitor_entry_t * )e_tmp->e_private; 464 e = mp->mp_next; 465 466 ch_free( mp ); 467 e_tmp->e_private = NULL; 468 entry_free( e_tmp ); 469 470 e_tmp = e; 471 } 472 rc = rs->sr_err = LDAP_OTHER; 473 break; 474 } 475 mp = ( monitor_entry_t * )e->e_private; 476 mp->mp_next = e_tmp; 477 e_tmp = e; 478 } 479 connection_done( c ); 480 *ep = e; 481 482 } else { 483 Connection *c; 484 int connindex; 485 unsigned long connid; 486 char *next = NULL; 487 static struct berval nconn_bv = BER_BVC( "cn=connection " ); 488 489 rc = LDAP_NO_SUCH_OBJECT; 490 491 /* create exactly the required entry; 492 * the normalized DN must start with "cn=connection ", 493 * followed by the connection id, followed by 494 * the RDN separator "," */ 495 if ( ndn->bv_len <= nconn_bv.bv_len 496 || strncmp( ndn->bv_val, nconn_bv.bv_val, nconn_bv.bv_len ) != 0 ) 497 { 498 return -1; 499 } 500 501 connid = strtol( &ndn->bv_val[ nconn_bv.bv_len ], &next, 10 ); 502 if ( next[ 0 ] != ',' ) { 503 return ( rs->sr_err = LDAP_OTHER ); 504 } 505 506 for ( c = connection_first( &connindex ); 507 c != NULL; 508 c = connection_next( c, &connindex ) ) 509 { 510 if ( c->c_connid == connid ) { 511 rc = conn_create( mi, c, ep, ms ); 512 if ( rc != SLAP_CB_CONTINUE ) { 513 rs->sr_err = rc; 514 515 } else if ( *ep == NULL ) { 516 rc = rs->sr_err = LDAP_OTHER; 517 } 518 519 break; 520 } 521 } 522 523 connection_done( c ); 524 } 525 526 return rc; 527} 528 529