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