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