1 /* $NetBSD: conn.c,v 1.3 2021/08/14 16:15:00 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-2021 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.3 2021/08/14 16:15:00 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
monitor_subsys_conn_init(BackendDB * be,monitor_subsys_t * ms)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 );
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 );
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 );
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 );
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 );
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 );
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 );
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
monitor_subsys_conn_update(Operation * op,SlapReply * rs,Entry * e)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() - SLAPD_SYNC_SYNCCONN_OFFSET;
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 /* Ignore outbound connections */
238 if ( c->c_conn_state == SLAP_C_CLIENT )
239 n--;
240 }
241 connection_done( c );
242 }
243
244 if ( n != -1 ) {
245 Attribute *a;
246 char buf[LDAP_PVT_INTTYPE_CHARS(long)];
247 ber_len_t len;
248
249 a = attr_find( e->e_attrs, mi->mi_ad_monitorCounter );
250 if ( a == NULL ) {
251 return( -1 );
252 }
253
254 snprintf( buf, sizeof( buf ), "%ld", n );
255 len = strlen( buf );
256 if ( len > a->a_vals[ 0 ].bv_len ) {
257 a->a_vals[ 0 ].bv_val = ber_memrealloc( a->a_vals[ 0 ].bv_val, len + 1 );
258 }
259 a->a_vals[ 0 ].bv_len = len;
260 AC_MEMCPY( a->a_vals[ 0 ].bv_val, buf, len + 1 );
261
262 /* FIXME: touch modifyTimestamp? */
263 }
264
265 return SLAP_CB_CONTINUE;
266 }
267
268 static int
conn_create(monitor_info_t * mi,Connection * c,Entry ** ep,monitor_subsys_t * ms)269 conn_create(
270 monitor_info_t *mi,
271 Connection *c,
272 Entry **ep,
273 monitor_subsys_t *ms )
274 {
275 monitor_entry_t *mp;
276 struct tm tm;
277 char buf[ BACKMONITOR_BUFSIZE ];
278 char buf2[ LDAP_LUTIL_GENTIME_BUFSIZE ];
279 char buf3[ LDAP_LUTIL_GENTIME_BUFSIZE ];
280
281 struct berval bv, ctmbv, mtmbv;
282 struct berval bv_unknown= BER_BVC("unknown");
283
284 Entry *e;
285
286 assert( c != NULL );
287 assert( ep != NULL );
288
289 ldap_pvt_gmtime( &c->c_starttime, &tm );
290
291 ctmbv.bv_len = lutil_gentime( buf2, sizeof( buf2 ), &tm );
292 ctmbv.bv_val = buf2;
293
294 ldap_pvt_gmtime( &c->c_activitytime, &tm );
295 mtmbv.bv_len = lutil_gentime( buf3, sizeof( buf3 ), &tm );
296 mtmbv.bv_val = buf3;
297
298 bv.bv_len = snprintf( buf, sizeof( buf ),
299 "cn=Connection %ld", c->c_connid );
300 bv.bv_val = buf;
301 e = monitor_entry_stub( &ms->mss_dn, &ms->mss_ndn, &bv,
302 mi->mi_oc_monitorConnection, &ctmbv, &mtmbv );
303
304 if ( e == NULL) {
305 Debug( LDAP_DEBUG_ANY,
306 "monitor_subsys_conn_create: "
307 "unable to create entry "
308 "\"cn=Connection %ld,%s\"\n",
309 c->c_connid,
310 ms->mss_dn.bv_val );
311 return( -1 );
312 }
313
314 #ifdef MONITOR_LEGACY_CONN
315 /* NOTE: this will disappear, as the exploded data
316 * has been moved to dedicated attributes */
317 bv.bv_len = snprintf( buf, sizeof( buf ),
318 "%ld "
319 ": %ld "
320 ": %ld/%ld/%ld/%ld "
321 ": %ld/%ld/%ld "
322 ": %s%s%s%s%s%s "
323 ": %s "
324 ": %s "
325 ": %s "
326 ": %s "
327 ": %s "
328 ": %s "
329 ": %s",
330 c->c_connid,
331 (long) c->c_protocol,
332 c->c_n_ops_received, c->c_n_ops_executing,
333 c->c_n_ops_pending, c->c_n_ops_completed,
334
335 /* add low-level counters here */
336 c->c_n_get, c->c_n_read, c->c_n_write,
337
338 c->c_currentber ? "r" : "",
339 c->c_writewaiter ? "w" : "",
340 LDAP_STAILQ_EMPTY( &c->c_ops ) ? "" : "x",
341 LDAP_STAILQ_EMPTY( &c->c_pending_ops ) ? "" : "p",
342 connection_state2str( c->c_conn_state ),
343 c->c_sasl_bind_in_progress ? "S" : "",
344
345 c->c_dn.bv_len ? c->c_dn.bv_val : SLAPD_ANONYMOUS,
346
347 c->c_listener_url.bv_val,
348 BER_BVISNULL( &c->c_peer_domain )
349 ? "" : c->c_peer_domain.bv_val,
350 BER_BVISNULL( &c->c_peer_name )
351 ? "" : c->c_peer_name.bv_val,
352 c->c_sock_name.bv_val,
353
354 buf2,
355 buf3 );
356 attr_merge_normalize_one( e, mi->mi_ad_monitoredInfo, &bv, NULL );
357 #endif /* MONITOR_LEGACY_CONN */
358
359 bv.bv_len = snprintf( buf, sizeof( buf ), "%lu", c->c_connid );
360 attr_merge_one( e, mi->mi_ad_monitorConnectionNumber, &bv, NULL );
361
362 bv.bv_len = snprintf( buf, sizeof( buf ), "%ld", (long) c->c_protocol );
363 attr_merge_normalize_one( e, mi->mi_ad_monitorConnectionProtocol, &bv, NULL );
364
365 bv.bv_len = snprintf( buf, sizeof( buf ), "%ld", c->c_n_ops_received );
366 attr_merge_one( e, mi->mi_ad_monitorConnectionOpsReceived, &bv, NULL );
367
368 bv.bv_len = snprintf( buf, sizeof( buf ), "%ld", c->c_n_ops_executing );
369 attr_merge_one( e, mi->mi_ad_monitorConnectionOpsExecuting, &bv, NULL );
370
371 bv.bv_len = snprintf( buf, sizeof( buf ), "%ld", c->c_n_ops_pending );
372 attr_merge_one( e, mi->mi_ad_monitorConnectionOpsPending, &bv, NULL );
373
374 bv.bv_len = snprintf( buf, sizeof( buf ), "%ld", c->c_n_ops_completed );
375 attr_merge_one( e, mi->mi_ad_monitorConnectionOpsCompleted, &bv, NULL );
376
377 bv.bv_len = snprintf( buf, sizeof( buf ), "%ld", c->c_n_get );
378 attr_merge_one( e, mi->mi_ad_monitorConnectionGet, &bv, NULL );
379
380 bv.bv_len = snprintf( buf, sizeof( buf ), "%ld", c->c_n_read );
381 attr_merge_one( e, mi->mi_ad_monitorConnectionRead, &bv, NULL );
382
383 bv.bv_len = snprintf( buf, sizeof( buf ), "%ld", c->c_n_write );
384 attr_merge_one( e, mi->mi_ad_monitorConnectionWrite, &bv, NULL );
385
386 bv.bv_len = snprintf( buf, sizeof( buf ), "%s%s%s%s%s%s",
387 c->c_currentber ? "r" : "",
388 c->c_writewaiter ? "w" : "",
389 LDAP_STAILQ_EMPTY( &c->c_ops ) ? "" : "x",
390 LDAP_STAILQ_EMPTY( &c->c_pending_ops ) ? "" : "p",
391 connection_state2str( c->c_conn_state ),
392 c->c_sasl_bind_in_progress ? "S" : "" );
393 attr_merge_normalize_one( e, mi->mi_ad_monitorConnectionMask, &bv, NULL );
394
395 attr_merge_one( e, mi->mi_ad_monitorConnectionAuthzDN,
396 &c->c_dn, &c->c_ndn );
397
398 /* NOTE: client connections leave the c_peer_* fields NULL */
399 assert( !BER_BVISNULL( &c->c_listener_url ) );
400 attr_merge_normalize_one( e, mi->mi_ad_monitorConnectionListener,
401 &c->c_listener_url, NULL );
402
403 attr_merge_normalize_one( e, mi->mi_ad_monitorConnectionPeerDomain,
404 BER_BVISNULL( &c->c_peer_domain ) ? &bv_unknown : &c->c_peer_domain,
405 NULL );
406
407 attr_merge_normalize_one( e, mi->mi_ad_monitorConnectionPeerAddress,
408 BER_BVISNULL( &c->c_peer_name ) ? &bv_unknown : &c->c_peer_name,
409 NULL );
410
411 assert( !BER_BVISNULL( &c->c_sock_name ) );
412 attr_merge_normalize_one( e, mi->mi_ad_monitorConnectionLocalAddress,
413 &c->c_sock_name, NULL );
414
415 attr_merge_normalize_one( e, mi->mi_ad_monitorConnectionStartTime, &ctmbv, NULL );
416
417 attr_merge_normalize_one( e, mi->mi_ad_monitorConnectionActivityTime, &mtmbv, NULL );
418
419 mp = monitor_entrypriv_create();
420 if ( mp == NULL ) {
421 return LDAP_OTHER;
422 }
423 e->e_private = ( void * )mp;
424 mp->mp_info = ms;
425 mp->mp_flags = MONITOR_F_SUB | MONITOR_F_VOLATILE;
426
427 *ep = e;
428
429 return SLAP_CB_CONTINUE;
430 }
431
432 static int
monitor_subsys_conn_create(Operation * op,SlapReply * rs,struct berval * ndn,Entry * e_parent,Entry ** ep)433 monitor_subsys_conn_create(
434 Operation *op,
435 SlapReply *rs,
436 struct berval *ndn,
437 Entry *e_parent,
438 Entry **ep )
439 {
440 monitor_info_t *mi = ( monitor_info_t * )op->o_bd->be_private;
441
442 int rc = SLAP_CB_CONTINUE;
443 monitor_subsys_t *ms;
444
445 assert( mi != NULL );
446 assert( e_parent != NULL );
447 assert( ep != NULL );
448
449 ms = (( monitor_entry_t *)e_parent->e_private)->mp_info;
450
451 *ep = NULL;
452
453 if ( ndn == NULL ) {
454 Connection *c;
455 ber_socket_t connindex;
456 Entry *e = NULL,
457 *e_tmp = NULL;
458
459 /* create all the children of e_parent */
460 for ( c = connection_first( &connindex );
461 c != NULL;
462 c = connection_next( c, &connindex ) )
463 {
464 monitor_entry_t *mp;
465
466 /* ignore outbound for now, nothing to show */
467 if ( c->c_conn_state == SLAP_C_CLIENT )
468 continue;
469
470 if ( conn_create( mi, c, &e, ms ) != SLAP_CB_CONTINUE
471 || e == NULL )
472 {
473 for ( ; e_tmp != NULL; ) {
474 mp = ( monitor_entry_t * )e_tmp->e_private;
475 e = mp->mp_next;
476
477 ch_free( mp );
478 e_tmp->e_private = NULL;
479 entry_free( e_tmp );
480
481 e_tmp = e;
482 }
483 rc = rs->sr_err = LDAP_OTHER;
484 break;
485 }
486 mp = ( monitor_entry_t * )e->e_private;
487 mp->mp_next = e_tmp;
488 e_tmp = e;
489 }
490 connection_done( c );
491 *ep = e;
492
493 } else {
494 Connection *c;
495 ber_socket_t connindex;
496 unsigned long connid;
497 char *next = NULL;
498 static struct berval nconn_bv = BER_BVC( "cn=connection " );
499
500 rc = LDAP_NO_SUCH_OBJECT;
501
502 /* create exactly the required entry;
503 * the normalized DN must start with "cn=connection ",
504 * followed by the connection id, followed by
505 * the RDN separator "," */
506 if ( ndn->bv_len <= nconn_bv.bv_len
507 || strncmp( ndn->bv_val, nconn_bv.bv_val, nconn_bv.bv_len ) != 0 )
508 {
509 return -1;
510 }
511
512 connid = strtol( &ndn->bv_val[ nconn_bv.bv_len ], &next, 10 );
513 if ( next[ 0 ] != ',' ) {
514 return ( rs->sr_err = LDAP_OTHER );
515 }
516
517 for ( c = connection_first( &connindex );
518 c != NULL;
519 c = connection_next( c, &connindex ) )
520 {
521 if ( c->c_connid == connid ) {
522 rc = conn_create( mi, c, ep, ms );
523 if ( rc != SLAP_CB_CONTINUE ) {
524 rs->sr_err = rc;
525
526 } else if ( *ep == NULL ) {
527 rc = rs->sr_err = LDAP_OTHER;
528 }
529
530 break;
531 }
532 }
533
534 connection_done( c );
535 }
536
537 return rc;
538 }
539
540