Back to index

openldap  2.4.31
conn.c
Go to the documentation of this file.
00001 /* conn.c - deal with connection subsystem */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 2001-2012 The OpenLDAP Foundation.
00006  * Portions Copyright 2001-2003 Pierangelo Masarati.
00007  * All rights reserved.
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted only as authorized by the OpenLDAP
00011  * Public License.
00012  *
00013  * A copy of this license is available in file LICENSE in the
00014  * top-level directory of the distribution or, alternatively, at
00015  * <http://www.OpenLDAP.org/license.html>.
00016  */
00017 /* ACKNOWLEDGEMENTS:
00018  * This work was initially developed by Pierangelo Masarati for inclusion
00019  * in OpenLDAP Software.
00020  */
00021 
00022 #include "portable.h"
00023 
00024 #include <stdio.h>
00025 #include <ac/string.h>
00026 
00027 #include "slap.h"
00028 #include "lutil.h"
00029 #include "back-monitor.h"
00030 
00031 static int
00032 monitor_subsys_conn_update(
00033        Operation            *op,
00034        SlapReply            *rs,
00035        Entry                   *e );
00036 
00037 static int 
00038 monitor_subsys_conn_create( 
00039        Operation            *op,
00040        SlapReply            *rs,
00041        struct berval        *ndn,
00042        Entry                *e_parent,
00043        Entry                **ep );
00044 
00045 int
00046 monitor_subsys_conn_init(
00047        BackendDB            *be,
00048        monitor_subsys_t     *ms )
00049 {
00050        monitor_info_t       *mi;
00051        Entry         *e, **ep, *e_conn;
00052        monitor_entry_t      *mp;
00053        char          buf[ BACKMONITOR_BUFSIZE ];
00054        struct berval bv;
00055 
00056        assert( be != NULL );
00057 
00058        ms->mss_update = monitor_subsys_conn_update;
00059        ms->mss_create = monitor_subsys_conn_create;
00060 
00061        mi = ( monitor_info_t * )be->be_private;
00062 
00063        if ( monitor_cache_get( mi, &ms->mss_ndn, &e_conn ) ) {
00064               Debug( LDAP_DEBUG_ANY,
00065                      "monitor_subsys_conn_init: "
00066                      "unable to get entry \"%s\"\n",
00067                      ms->mss_ndn.bv_val, 0, 0 );
00068               return( -1 );
00069        }
00070 
00071        mp = ( monitor_entry_t * )e_conn->e_private;
00072        mp->mp_children = NULL;
00073        ep = &mp->mp_children;
00074 
00075        /*
00076         * Max file descriptors
00077         */
00078        BER_BVSTR( &bv, "cn=Max File Descriptors" );
00079        e = monitor_entry_stub( &ms->mss_dn, &ms->mss_ndn, &bv,
00080               mi->mi_oc_monitorCounterObject, mi, NULL, NULL );
00081        
00082        if ( e == NULL ) {
00083               Debug( LDAP_DEBUG_ANY,
00084                      "monitor_subsys_conn_init: "
00085                      "unable to create entry \"%s,%s\"\n",
00086                      bv.bv_val, ms->mss_ndn.bv_val, 0 );
00087               return( -1 );
00088        }
00089 
00090        if ( dtblsize ) {
00091               bv.bv_val = buf;
00092               bv.bv_len = snprintf( buf, sizeof( buf ), "%d", dtblsize );
00093 
00094        } else {
00095               BER_BVSTR( &bv, "0" );
00096        }
00097        attr_merge_one( e, mi->mi_ad_monitorCounter, &bv, NULL );
00098        
00099        mp = monitor_entrypriv_create();
00100        if ( mp == NULL ) {
00101               return -1;
00102        }
00103        e->e_private = ( void * )mp;
00104        mp->mp_info = ms;
00105        mp->mp_flags = ms->mss_flags \
00106               | MONITOR_F_SUB | MONITOR_F_PERSISTENT;
00107        mp->mp_flags &= ~MONITOR_F_VOLATILE_CH;
00108 
00109        if ( monitor_cache_add( mi, e ) ) {
00110               Debug( LDAP_DEBUG_ANY,
00111                      "monitor_subsys_conn_init: "
00112                      "unable to add entry \"cn=Total,%s\"\n",
00113                      ms->mss_ndn.bv_val, 0, 0 );
00114               return( -1 );
00115        }
00116 
00117        *ep = e;
00118        ep = &mp->mp_next;
00119        
00120        /*
00121         * Total conns
00122         */
00123        BER_BVSTR( &bv, "cn=Total" );
00124        e = monitor_entry_stub( &ms->mss_dn, &ms->mss_ndn, &bv,
00125               mi->mi_oc_monitorCounterObject, mi, NULL, NULL );
00126        
00127        if ( e == NULL ) {
00128               Debug( LDAP_DEBUG_ANY,
00129                      "monitor_subsys_conn_init: "
00130                      "unable to create entry \"cn=Total,%s\"\n",
00131                      ms->mss_ndn.bv_val, 0, 0 );
00132               return( -1 );
00133        }
00134        
00135        BER_BVSTR( &bv, "-1" );
00136        attr_merge_one( e, mi->mi_ad_monitorCounter, &bv, NULL );
00137        
00138        mp = monitor_entrypriv_create();
00139        if ( mp == NULL ) {
00140               return -1;
00141        }
00142        e->e_private = ( void * )mp;
00143        mp->mp_info = ms;
00144        mp->mp_flags = ms->mss_flags \
00145               | MONITOR_F_SUB | MONITOR_F_PERSISTENT;
00146        mp->mp_flags &= ~MONITOR_F_VOLATILE_CH;
00147 
00148        if ( monitor_cache_add( mi, e ) ) {
00149               Debug( LDAP_DEBUG_ANY,
00150                      "monitor_subsys_conn_init: "
00151                      "unable to add entry \"cn=Total,%s\"\n",
00152                      ms->mss_ndn.bv_val, 0, 0 );
00153               return( -1 );
00154        }
00155 
00156        *ep = e;
00157        ep = &mp->mp_next;
00158        
00159        /*
00160         * Current conns
00161         */
00162        BER_BVSTR( &bv, "cn=Current" );
00163        e = monitor_entry_stub( &ms->mss_dn, &ms->mss_ndn, &bv,
00164               mi->mi_oc_monitorCounterObject, mi, NULL, NULL );
00165 
00166        if ( e == NULL ) {
00167               Debug( LDAP_DEBUG_ANY,
00168                      "monitor_subsys_conn_init: "
00169                      "unable to create entry \"cn=Current,%s\"\n",
00170                      ms->mss_ndn.bv_val, 0, 0 );
00171               return( -1 );
00172        }
00173        
00174        BER_BVSTR( &bv, "0" );
00175        attr_merge_one( e, mi->mi_ad_monitorCounter, &bv, NULL );
00176        
00177        mp = monitor_entrypriv_create();
00178        if ( mp == NULL ) {
00179               return -1;
00180        }
00181        e->e_private = ( void * )mp;
00182        mp->mp_info = ms;
00183        mp->mp_flags = ms->mss_flags \
00184               | MONITOR_F_SUB | MONITOR_F_PERSISTENT;
00185        mp->mp_flags &= ~MONITOR_F_VOLATILE_CH;
00186 
00187        if ( monitor_cache_add( mi, e ) ) {
00188               Debug( LDAP_DEBUG_ANY,
00189                      "monitor_subsys_conn_init: "
00190                      "unable to add entry \"cn=Current,%s\"\n",
00191                      ms->mss_ndn.bv_val, 0, 0 );
00192               return( -1 );
00193        }
00194        
00195        *ep = e;
00196        ep = &mp->mp_next;
00197 
00198        monitor_cache_release( mi, e_conn );
00199 
00200        return( 0 );
00201 }
00202 
00203 static int
00204 monitor_subsys_conn_update(
00205        Operation            *op,
00206        SlapReply            *rs,
00207        Entry                   *e )
00208 {
00209        monitor_info_t       *mi = ( monitor_info_t * )op->o_bd->be_private;
00210 
00211        long                 n = -1;
00212        static struct berval total_bv = BER_BVC( "cn=total" ),
00213                             current_bv = BER_BVC( "cn=current" );
00214        struct berval        rdn;
00215 
00216        assert( mi != NULL );
00217        assert( e != NULL );
00218 
00219        dnRdn( &e->e_nname, &rdn );
00220        
00221        if ( dn_match( &rdn, &total_bv ) ) {
00222               n = connections_nextid();
00223 
00224        } else if ( dn_match( &rdn, &current_bv ) ) {
00225               Connection    *c;
00226               ber_socket_t  connindex;
00227 
00228               for ( n = 0, c = connection_first( &connindex );
00229                             c != NULL;
00230                             n++, c = connection_next( c, &connindex ) )
00231               {
00232                      /* No Op */ ;
00233               }
00234               connection_done( c );
00235        }
00236 
00237        if ( n != -1 ) {
00238               Attribute     *a;
00239               char          buf[LDAP_PVT_INTTYPE_CHARS(long)];
00240               ber_len_t     len;
00241 
00242               a = attr_find( e->e_attrs, mi->mi_ad_monitorCounter );
00243               if ( a == NULL ) {
00244                      return( -1 );
00245               }
00246 
00247               snprintf( buf, sizeof( buf ), "%ld", n );
00248               len = strlen( buf );
00249               if ( len > a->a_vals[ 0 ].bv_len ) {
00250                      a->a_vals[ 0 ].bv_val = ber_memrealloc( a->a_vals[ 0 ].bv_val, len + 1 );
00251               }
00252               a->a_vals[ 0 ].bv_len = len;
00253               AC_MEMCPY( a->a_vals[ 0 ].bv_val, buf, len + 1 );
00254 
00255               /* FIXME: touch modifyTimestamp? */
00256        }
00257 
00258        return SLAP_CB_CONTINUE;
00259 }
00260 
00261 static int
00262 conn_create(
00263        monitor_info_t              *mi,
00264        Connection           *c,
00265        Entry                **ep,
00266        monitor_subsys_t     *ms )
00267 {
00268        monitor_entry_t *mp;
00269        struct tm     tm;
00270        char          buf[ BACKMONITOR_BUFSIZE ];
00271        char          buf2[ LDAP_LUTIL_GENTIME_BUFSIZE ];
00272        char          buf3[ LDAP_LUTIL_GENTIME_BUFSIZE ];
00273 
00274        struct berval bv, ctmbv, mtmbv;
00275        struct berval bv_unknown= BER_BVC("unknown");
00276 
00277        Entry         *e;
00278 
00279        assert( c != NULL );
00280        assert( ep != NULL );
00281 
00282        ldap_pvt_gmtime( &c->c_starttime, &tm );
00283 
00284        ctmbv.bv_len = lutil_gentime( buf2, sizeof( buf2 ), &tm );
00285        ctmbv.bv_val = buf2;
00286 
00287        ldap_pvt_gmtime( &c->c_activitytime, &tm );
00288        mtmbv.bv_len = lutil_gentime( buf3, sizeof( buf3 ), &tm );
00289        mtmbv.bv_val = buf3;
00290 
00291        bv.bv_len = snprintf( buf, sizeof( buf ),
00292               "cn=Connection %ld", c->c_connid );
00293        bv.bv_val = buf;
00294        e = monitor_entry_stub( &ms->mss_dn, &ms->mss_ndn, &bv, 
00295               mi->mi_oc_monitorConnection, mi, &ctmbv, &mtmbv );
00296 
00297        if ( e == NULL) {
00298               Debug( LDAP_DEBUG_ANY,
00299                      "monitor_subsys_conn_create: "
00300                      "unable to create entry "
00301                      "\"cn=Connection %ld,%s\"\n",
00302                      c->c_connid, 
00303                      ms->mss_dn.bv_val, 0 );
00304               return( -1 );
00305        }
00306 
00307 #ifdef MONITOR_LEGACY_CONN
00308        /* NOTE: this will disappear, as the exploded data
00309         * has been moved to dedicated attributes */
00310        bv.bv_len = snprintf( buf, sizeof( buf ),
00311                      "%ld "
00312                      ": %ld "
00313                      ": %ld/%ld/%ld/%ld "
00314                      ": %ld/%ld/%ld "
00315                      ": %s%s%s%s%s%s "
00316                      ": %s "
00317                      ": %s "
00318                      ": %s "
00319                      ": %s "
00320                      ": %s "
00321                      ": %s "
00322                      ": %s",
00323                      c->c_connid,
00324                      (long) c->c_protocol,
00325                      c->c_n_ops_received, c->c_n_ops_executing,
00326                             c->c_n_ops_pending, c->c_n_ops_completed,
00327                      
00328                      /* add low-level counters here */
00329                      c->c_n_get, c->c_n_read, c->c_n_write,
00330                      
00331                      c->c_currentber ? "r" : "",
00332                      c->c_writewaiter ? "w" : "",
00333                      LDAP_STAILQ_EMPTY( &c->c_ops ) ? "" : "x",
00334                      LDAP_STAILQ_EMPTY( &c->c_pending_ops ) ? "" : "p",
00335                      connection_state2str( c->c_conn_state ),
00336                      c->c_sasl_bind_in_progress ? "S" : "",
00337                      
00338                      c->c_dn.bv_len ? c->c_dn.bv_val : SLAPD_ANONYMOUS,
00339                      
00340                      c->c_listener_url.bv_val,
00341                      BER_BVISNULL( &c->c_peer_domain )
00342                             ? "" : c->c_peer_domain.bv_val,
00343                      BER_BVISNULL( &c->c_peer_name )
00344                             ? "" : c->c_peer_name.bv_val,
00345                      c->c_sock_name.bv_val,
00346                      
00347                      buf2,
00348                      buf3 );
00349        attr_merge_normalize_one( e, mi->mi_ad_monitoredInfo, &bv, NULL );
00350 #endif /* MONITOR_LEGACY_CONN */
00351 
00352        bv.bv_len = snprintf( buf, sizeof( buf ), "%lu", c->c_connid );
00353        attr_merge_one( e, mi->mi_ad_monitorConnectionNumber, &bv, NULL );
00354 
00355        bv.bv_len = snprintf( buf, sizeof( buf ), "%ld", (long) c->c_protocol );
00356        attr_merge_normalize_one( e, mi->mi_ad_monitorConnectionProtocol, &bv, NULL );
00357 
00358        bv.bv_len = snprintf( buf, sizeof( buf ), "%ld", c->c_n_ops_received );
00359        attr_merge_one( e, mi->mi_ad_monitorConnectionOpsReceived, &bv, NULL );
00360 
00361        bv.bv_len = snprintf( buf, sizeof( buf ), "%ld", c->c_n_ops_executing );
00362        attr_merge_one( e, mi->mi_ad_monitorConnectionOpsExecuting, &bv, NULL );
00363 
00364        bv.bv_len = snprintf( buf, sizeof( buf ), "%ld", c->c_n_ops_pending );
00365        attr_merge_one( e, mi->mi_ad_monitorConnectionOpsPending, &bv, NULL );
00366 
00367        bv.bv_len = snprintf( buf, sizeof( buf ), "%ld", c->c_n_ops_completed );
00368        attr_merge_one( e, mi->mi_ad_monitorConnectionOpsCompleted, &bv, NULL );
00369 
00370        bv.bv_len = snprintf( buf, sizeof( buf ), "%ld", c->c_n_get );
00371        attr_merge_one( e, mi->mi_ad_monitorConnectionGet, &bv, NULL );
00372 
00373        bv.bv_len = snprintf( buf, sizeof( buf ), "%ld", c->c_n_read );
00374        attr_merge_one( e, mi->mi_ad_monitorConnectionRead, &bv, NULL );
00375 
00376        bv.bv_len = snprintf( buf, sizeof( buf ), "%ld", c->c_n_write );
00377        attr_merge_one( e, mi->mi_ad_monitorConnectionWrite, &bv, NULL );
00378 
00379        bv.bv_len = snprintf( buf, sizeof( buf ), "%s%s%s%s%s%s",
00380                      c->c_currentber ? "r" : "",
00381                      c->c_writewaiter ? "w" : "",
00382                      LDAP_STAILQ_EMPTY( &c->c_ops ) ? "" : "x",
00383                      LDAP_STAILQ_EMPTY( &c->c_pending_ops ) ? "" : "p",
00384                      connection_state2str( c->c_conn_state ),
00385                      c->c_sasl_bind_in_progress ? "S" : "" );
00386        attr_merge_normalize_one( e, mi->mi_ad_monitorConnectionMask, &bv, NULL );
00387 
00388        attr_merge_one( e, mi->mi_ad_monitorConnectionAuthzDN,
00389               &c->c_dn, &c->c_ndn );
00390 
00391        /* NOTE: client connections leave the c_peer_* fields NULL */
00392        assert( !BER_BVISNULL( &c->c_listener_url ) );
00393        attr_merge_normalize_one( e, mi->mi_ad_monitorConnectionListener,
00394               &c->c_listener_url, NULL );
00395 
00396        attr_merge_normalize_one( e, mi->mi_ad_monitorConnectionPeerDomain,
00397               BER_BVISNULL( &c->c_peer_domain ) ? &bv_unknown : &c->c_peer_domain,
00398               NULL );
00399 
00400        attr_merge_normalize_one( e, mi->mi_ad_monitorConnectionPeerAddress,
00401               BER_BVISNULL( &c->c_peer_name ) ? &bv_unknown : &c->c_peer_name,
00402               NULL );
00403 
00404        assert( !BER_BVISNULL( &c->c_sock_name ) );
00405        attr_merge_normalize_one( e, mi->mi_ad_monitorConnectionLocalAddress,
00406               &c->c_sock_name, NULL );
00407 
00408        attr_merge_normalize_one( e, mi->mi_ad_monitorConnectionStartTime, &ctmbv, NULL );
00409 
00410        attr_merge_normalize_one( e, mi->mi_ad_monitorConnectionActivityTime, &mtmbv, NULL );
00411 
00412        mp = monitor_entrypriv_create();
00413        if ( mp == NULL ) {
00414               return LDAP_OTHER;
00415        }
00416        e->e_private = ( void * )mp;
00417        mp->mp_info = ms;
00418        mp->mp_flags = MONITOR_F_SUB | MONITOR_F_VOLATILE;
00419 
00420        *ep = e;
00421 
00422        return SLAP_CB_CONTINUE;
00423 }
00424 
00425 static int 
00426 monitor_subsys_conn_create( 
00427        Operation            *op,
00428        SlapReply            *rs,
00429        struct berval        *ndn,
00430        Entry                *e_parent,
00431        Entry                **ep )
00432 {
00433        monitor_info_t       *mi = ( monitor_info_t * )op->o_bd->be_private;
00434 
00435        int                  rc = SLAP_CB_CONTINUE;
00436        monitor_subsys_t     *ms;
00437 
00438        assert( mi != NULL );
00439        assert( e_parent != NULL );
00440        assert( ep != NULL );
00441 
00442        ms = (( monitor_entry_t *)e_parent->e_private)->mp_info;
00443 
00444        *ep = NULL;
00445 
00446        if ( ndn == NULL ) {
00447               Connection    *c;
00448               ber_socket_t  connindex;
00449               Entry         *e = NULL,
00450                             *e_tmp = NULL;
00451 
00452               /* create all the children of e_parent */
00453               for ( c = connection_first( &connindex );
00454                             c != NULL;
00455                             c = connection_next( c, &connindex ) )
00456               {
00457                      monitor_entry_t      *mp;
00458 
00459                      if ( conn_create( mi, c, &e, ms ) != SLAP_CB_CONTINUE
00460                                    || e == NULL )
00461                      {
00462                             for ( ; e_tmp != NULL; ) {
00463                                    mp = ( monitor_entry_t * )e_tmp->e_private;
00464                                    e = mp->mp_next;
00465 
00466                                    ch_free( mp );
00467                                    e_tmp->e_private = NULL;
00468                                    entry_free( e_tmp );
00469 
00470                                    e_tmp = e;
00471                             }
00472                             rc = rs->sr_err = LDAP_OTHER;
00473                             break;
00474                      }
00475                      mp = ( monitor_entry_t * )e->e_private;
00476                      mp->mp_next = e_tmp;
00477                      e_tmp = e;
00478               }
00479               connection_done( c );
00480               *ep = e;
00481 
00482        } else {
00483               Connection           *c;
00484               ber_socket_t         connindex;
00485               unsigned long               connid;
00486               char                 *next = NULL;
00487               static struct berval nconn_bv = BER_BVC( "cn=connection " );
00488 
00489               rc = LDAP_NO_SUCH_OBJECT;
00490               
00491               /* create exactly the required entry;
00492                * the normalized DN must start with "cn=connection ",
00493                * followed by the connection id, followed by
00494                * the RDN separator "," */
00495               if ( ndn->bv_len <= nconn_bv.bv_len
00496                             || strncmp( ndn->bv_val, nconn_bv.bv_val, nconn_bv.bv_len ) != 0 )
00497               {
00498                      return -1;
00499               }
00500               
00501               connid = strtol( &ndn->bv_val[ nconn_bv.bv_len ], &next, 10 );
00502               if ( next[ 0 ] != ',' ) {
00503                      return ( rs->sr_err = LDAP_OTHER );
00504               }
00505 
00506               for ( c = connection_first( &connindex );
00507                             c != NULL;
00508                             c = connection_next( c, &connindex ) )
00509               {
00510                      if ( c->c_connid == connid ) {
00511                             rc = conn_create( mi, c, ep, ms );
00512                             if ( rc != SLAP_CB_CONTINUE ) {
00513                                    rs->sr_err = rc;
00514 
00515                             } else if ( *ep == NULL ) {
00516                                    rc = rs->sr_err = LDAP_OTHER;
00517                             }
00518 
00519                             break;
00520                      }
00521               }
00522               
00523               connection_done( c );
00524        }
00525 
00526        return rc;
00527 }
00528