xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/back-monitor/conn.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
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, &current_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