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