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