]> git.sur5r.net Git - openldap/blob - servers/slapd/back-monitor/log.c
improvements to monitor backend: added a log entry that lists the current log level...
[openldap] / servers / slapd / back-monitor / log.c
1 /* log.c - deal with log subsystem */
2 /*
3  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6 /*
7  * Copyright 2001 The OpenLDAP Foundation, All Rights Reserved.
8  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
9  * 
10  * Copyright 2001, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
11  * 
12  * This work has beed deveolped for the OpenLDAP Foundation 
13  * in the hope that it may be useful to the Open Source community, 
14  * but WITHOUT ANY WARRANTY.
15  * 
16  * Permission is granted to anyone to use this software for any purpose
17  * on any computer system, and to alter it and redistribute it, subject
18  * to the following restrictions:
19  * 
20  * 1. The author and SysNet s.n.c. are not responsible for the consequences
21  *    of use of this software, no matter how awful, even if they arise from
22  *    flaws in it.
23  * 
24  * 2. The origin of this software must not be misrepresented, either by
25  *    explicit claim or by omission.  Since few users ever read sources,
26  *    credits should appear in the documentation.
27  * 
28  * 3. Altered versions must be plainly marked as such, and must not be
29  *    misrepresented as being the original software.  Since few users
30  *    ever read sources, credits should appear in the documentation.
31  *    SysNet s.n.c. cannot be responsible for the consequences of the
32  *    alterations.
33  * 
34  * 4. This notice may not be removed or altered.
35  */
36
37 #include "portable.h"
38
39 #include <stdio.h>
40
41 #include <ac/string.h>
42
43 #include "slap.h"
44 #include "lutil.h"
45 #include "ldif.h"
46 #include "back-monitor.h"
47
48 /*
49  * log mutex
50  */
51 ldap_pvt_thread_mutex_t         monitor_log_mutex;
52
53 static struct {
54         int i;
55         const char *s;
56 } int_2_level[] = {
57         { LDAP_DEBUG_TRACE,     "Trace" },
58         { LDAP_DEBUG_PACKETS,   "Packets" },
59         { LDAP_DEBUG_ARGS,      "Args" },
60         { LDAP_DEBUG_CONNS,     "Conns" },
61         { LDAP_DEBUG_BER,       "BER" },
62         { LDAP_DEBUG_FILTER,    "Filter" },
63         { LDAP_DEBUG_CONFIG,    "Config" },     /* useless */
64         { LDAP_DEBUG_ACL,       "ACL" },
65         { LDAP_DEBUG_STATS,     "Stats" },
66         { LDAP_DEBUG_STATS2,    "Stats2" },
67         { LDAP_DEBUG_SHELL,     "Shell" },
68         { LDAP_DEBUG_PARSE,     "Parse" },
69         { LDAP_DEBUG_CACHE,     "Cache" },
70         { LDAP_DEBUG_INDEX,     "Index" },
71         { 0,                    NULL }
72 };
73
74 static int loglevel2int( const char *str );
75 static const char * int2loglevel( int n );
76
77 static int add_values( Entry *e, Modification *mod, int *newlevel );
78 static int delete_values( Entry *e, Modification *mod, int *newlevel );
79 static int replace_values( Entry *e, Modification *mod, int *newlevel );
80
81 /*
82  * initializes log subentry
83  */
84 int
85 monitor_subsys_log_init(
86         BackendDB       *be
87 )
88 {
89         struct monitorinfo      *mi;
90         Entry                   *e;
91         int                     i;
92         struct monitorentrypriv *mp;
93         struct berval           val, *bv[2] = { &val, NULL };
94
95         ldap_pvt_thread_mutex_init( &monitor_log_mutex );
96
97         mi = ( struct monitorinfo * )be->be_private;
98
99         if ( monitor_cache_get( mi, monitor_subsys[SLAPD_MONITOR_LOG].mss_ndn, 
100                                 &e ) ) {
101 #ifdef NEW_LOGGING
102                 LDAP_LOG(( "operation", LDAP_LEVEL_CRIT,
103                         "monitor_subsys_log_init: "
104                         "unable to get entry '%s'\n",
105                         monitor_subsys[SLAPD_MONITOR_LOG].mss_ndn ));
106 #else
107                 Debug( LDAP_DEBUG_ANY,
108                         "monitor_subsys_log_init: "
109                         "unable to get entry '%s'\n%s%s",
110                         monitor_subsys[SLAPD_MONITOR_LOG].mss_ndn, 
111                         "", "" );
112 #endif
113                 return( -1 );
114         }
115
116         /* initialize the debug level */
117         for ( i = 0; int_2_level[ i ].i != 0; i++ ) {
118                 if ( int_2_level[ i ].i & ldap_syslog ) {
119                         val.bv_val = ( char * )int_2_level[ i ].s;
120                         val.bv_len = strlen( val.bv_val );
121
122                         attr_merge( e, monitor_ad_desc, bv );
123                 }
124         }
125
126         monitor_cache_release( mi, e );
127
128         return( 0 );
129 }
130
131 int 
132 monitor_subsys_log_modify( 
133         struct monitorinfo      *mi,
134         Entry                   *e,
135         Modifications           *modlist
136 )
137 {
138         int             rc = LDAP_OTHER;
139         int             newlevel = ldap_syslog;
140         Attribute       *save_attrs;
141         Modifications   *ml;
142
143         ldap_pvt_thread_mutex_lock( &monitor_log_mutex );
144
145         save_attrs = e->e_attrs;
146         e->e_attrs = attrs_dup( e->e_attrs );
147
148         for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
149                 Modification    *mod = &ml->sml_mod;
150
151                 /*
152                  * Operational attributes
153                  */
154 #if 0
155                 if ( mod->sm_desc == slap_schema.si_ad_modifyTimestamp 
156                         || mod->sm_desc == slap_schema.si_ad_modifiersName ) {
157                         ( void ) attr_delete( &e->e_attrs, mod->sm_desc );
158                         rc = attr_merge( e, mod->sm_desc, mod->sm_bvalues );
159                         if ( rc != 0 ) {
160                                 rc = LDAP_OTHER;
161                                 break;
162                         }
163                         continue;
164
165                 /*
166                  * unhandled operational attributes
167                  */
168                 } else if ( is_at_operational( mod->sm_desc->ad_type ) ) {
169                         continue;
170
171 #else
172                 if ( is_at_operational( mod->sm_desc->ad_type ) ) {
173                         ( void ) attr_delete( &e->e_attrs, mod->sm_desc );
174                         rc = attr_merge( e, mod->sm_desc, mod->sm_bvalues );
175                         if ( rc != 0 ) {
176                                 rc = LDAP_OTHER;
177                                 break;
178                         }
179                         continue;
180
181 #endif
182                 /*
183                  * only the monitor description attribute can be modified
184                  */
185                 } else if ( mod->sm_desc != monitor_ad_desc ) {
186                         rc = LDAP_UNWILLING_TO_PERFORM;
187                         break;
188                 }
189
190                 switch ( mod->sm_op ) {
191                 case LDAP_MOD_ADD:
192                         rc = add_values( e, mod, &newlevel );
193                         break;
194                         
195                 case LDAP_MOD_DELETE:
196                         rc = delete_values( e, mod, &newlevel );
197                         break;
198
199                 case LDAP_MOD_REPLACE:
200                         rc = replace_values( e, mod, &newlevel );
201                         break;
202
203                 default:
204                         rc = LDAP_OPERATIONS_ERROR;
205                         break;
206                 }
207
208                 if ( rc != LDAP_SUCCESS ) {
209                         break;
210                 }
211         }
212
213         /* set the new debug level */
214         if ( rc == LDAP_SUCCESS ) {
215                 const char *text;
216                 static char textbuf[1024];
217
218 #if 0   /* need op */
219                 /* check for abandon */
220                 ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
221                 if ( op->o_abandon ) {
222                         ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
223                         rc = SLAPD_ABANDON;
224
225                         goto cleanup;
226                 }
227 #endif
228
229                 /* check that the entry still obeys the schema */
230                 rc = entry_schema_check( e, save_attrs, &text, textbuf, 
231                                 sizeof( textbuf ) );
232                 if ( rc != LDAP_SUCCESS ) {
233                         goto cleanup;
234                 }
235
236                 ldap_syslog = newlevel;
237
238 #if 0
239                 slap_debug = newlevel;
240                 lutil_set_debug_level( "slapd", slap_debug );
241                 ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &slap_debug);
242                 ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &slap_debug);
243                 ldif_debug = slap_debug;
244 #endif
245         }
246
247 cleanup:;
248         if ( rc == LDAP_SUCCESS ) {
249                 attrs_free( save_attrs );
250
251         } else {
252                 attrs_free( e->e_attrs );
253                 e->e_attrs = save_attrs;
254         }
255         
256         ldap_pvt_thread_mutex_unlock( &monitor_log_mutex );
257
258         return( rc );
259 }
260
261 static int
262 loglevel2int( const char *str )
263 {
264         int             i;
265         
266         for ( i = 0; int_2_level[ i ].i != 0; i++ ) {
267                 if ( strcasecmp( str, int_2_level[ i ].s ) == 0 ) {
268                         return int_2_level[ i ].i;
269                 }
270         }
271
272         return 0;
273 }
274
275 static const char *
276 int2loglevel( int n )
277 {
278         int             i;
279         
280         for ( i = 0; int_2_level[ i ].i != 0; i++ ) {
281                 if ( int_2_level[ i ].i == n ) {
282                         return int_2_level[ i ].s;
283                 }
284         }
285
286         return NULL;
287 }
288
289 static int
290 check_constraints( Modification *mod, int *newlevel )
291 {
292         int             i;
293
294         for ( i = 0; mod->sm_bvalues && mod->sm_bvalues[i] != NULL; i++ ) {
295                 int len, l;
296                 const char *s;
297                 
298                 l = loglevel2int( mod->sm_bvalues[i]->bv_val );
299                 if ( !l ) {
300                         return LDAP_CONSTRAINT_VIOLATION;
301                 }
302
303                 s = int2loglevel( l );
304                 len = strlen( s );
305                 assert( len == mod->sm_bvalues[i]->bv_len );
306                 
307                 AC_MEMCPY( mod->sm_bvalues[i]->bv_val, s, len );
308
309                 *newlevel |= l;
310         }
311
312         return LDAP_SUCCESS;
313 }       
314
315 static int 
316 add_values( Entry *e, Modification *mod, int *newlevel )
317 {
318         Attribute       *a;
319         int             i, rc;
320         MatchingRule    *mr = mod->sm_desc->ad_type->sat_equality;
321
322         rc = check_constraints( mod, newlevel );
323         if ( rc != LDAP_SUCCESS ) {
324                 return rc;
325         }
326
327         a = attr_find( e->e_attrs, mod->sm_desc );
328
329         if ( a != NULL ) {
330                 
331                 /* "description" SHOULD have appropriate rules ... */
332                 if ( mr == NULL || !mr->smr_match ) {
333                         return LDAP_INAPPROPRIATE_MATCHING;
334                 }
335
336                 for ( i = 0; mod->sm_bvalues[i] != NULL; i++ ) {
337                         int rc;
338                         int j;
339                         const char *text = NULL;
340                         struct berval *asserted;
341
342                         rc = value_normalize( mod->sm_desc,
343                                         SLAP_MR_EQUALITY,
344                                         mod->sm_bvalues[i],
345                                         &asserted,
346                                         &text );
347
348                         if ( rc != LDAP_SUCCESS ) {
349                                 return rc;
350                         }
351
352                         for ( j = 0; a->a_vals[j] != NULL; j++ ) {
353                                 int match;
354                                 int rc = value_match( &match, mod->sm_desc, mr,
355                                                 SLAP_MR_VALUE_SYNTAX_MATCH,
356                                                 a->a_vals[j], asserted, &text );
357
358                                 if ( rc == LDAP_SUCCESS && match == 0 ) {
359                                         ber_bvfree( asserted );
360                                         return LDAP_TYPE_OR_VALUE_EXISTS;
361                                 }
362                         }
363
364                         ber_bvfree( asserted );
365                 }
366         }
367
368         /* no - add them */
369         if ( attr_merge( e, mod->sm_desc, mod->sm_bvalues ) != 0 ) {
370                 /* this should return result return of attr_merge */
371                 return LDAP_OTHER;
372         }
373
374         return LDAP_SUCCESS;
375 }
376
377 static int
378 delete_values( Entry *e, Modification *mod, int *newlevel )
379 {
380         int             i, j, k, found, rc, nl = 0;
381         Attribute       *a;
382         char *desc = mod->sm_desc->ad_cname.bv_val;
383         MatchingRule *mr = mod->sm_desc->ad_type->sat_equality;
384
385         rc = check_constraints( mod, &nl );
386         if ( rc != LDAP_SUCCESS ) {
387                 return rc;
388         }
389
390         *newlevel &= ~nl;
391
392         /* delete the entire attribute */
393         if ( mod->sm_bvalues == NULL ) {
394                 int rc = attr_delete( &e->e_attrs, mod->sm_desc );
395
396                 if ( rc ) {
397                         rc = LDAP_NO_SUCH_ATTRIBUTE;
398                 } else {
399                         *newlevel = 0;
400                         rc = LDAP_SUCCESS;
401                 }
402                 return rc;
403         }
404
405         if ( mr == NULL || !mr->smr_match ) {
406                 /* disallow specific attributes from being deleted if
407                  * no equality rule */
408                 return LDAP_INAPPROPRIATE_MATCHING;
409         }
410
411         /* delete specific values - find the attribute first */
412         if ( (a = attr_find( e->e_attrs, mod->sm_desc )) == NULL ) {
413                 return( LDAP_NO_SUCH_ATTRIBUTE );
414         }
415
416         /* find each value to delete */
417         for ( i = 0; mod->sm_bvalues[i] != NULL; i++ ) {
418                 int rc;
419                 const char *text = NULL;
420
421                 struct berval *asserted;
422
423                 rc = value_normalize( mod->sm_desc,
424                                 SLAP_MR_EQUALITY,
425                                 mod->sm_bvalues[i],
426                                 &asserted,
427                                 &text );
428
429                 if( rc != LDAP_SUCCESS ) return rc;
430
431                 found = 0;
432                 for ( j = 0; a->a_vals[j] != NULL; j++ ) {
433                         int match;
434                         int rc = value_match( &match, mod->sm_desc, mr,
435                                         SLAP_MR_VALUE_SYNTAX_MATCH,
436                                         a->a_vals[j], asserted, &text );
437
438                         if( rc == LDAP_SUCCESS && match != 0 ) {
439                                 continue;
440                         }
441
442                         /* found a matching value */
443                         found = 1;
444
445                         /* delete it */
446                         ber_bvfree( a->a_vals[j] );
447                         for ( k = j + 1; a->a_vals[k] != NULL; k++ ) {
448                                 a->a_vals[k - 1] = a->a_vals[k];
449                         }
450                         a->a_vals[k - 1] = NULL;
451
452                         break;
453                 }
454
455                 ber_bvfree( asserted );
456
457                 /* looked through them all w/o finding it */
458                 if ( ! found ) {
459                         return LDAP_NO_SUCH_ATTRIBUTE;
460                 }
461         }
462
463         /* if no values remain, delete the entire attribute */
464         if ( a->a_vals[0] == NULL ) {
465                 /* should already be zero */
466                 *newlevel = 0;
467                 
468                 if ( attr_delete( &e->e_attrs, mod->sm_desc ) ) {
469                         return LDAP_NO_SUCH_ATTRIBUTE;
470                 }
471         }
472
473         return LDAP_SUCCESS;
474 }
475
476 static int
477 replace_values( Entry *e, Modification *mod, int *newlevel )
478 {
479         int i, rc;
480
481         *newlevel = 0;
482         rc = check_constraints( mod, newlevel );
483         if ( rc != LDAP_SUCCESS ) {
484                 return rc;
485         }
486
487         rc = attr_delete( &e->e_attrs, mod->sm_desc );
488
489         if ( rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_ATTRIBUTE ) {
490                 return rc;
491         }
492
493         if ( mod->sm_bvalues != NULL &&
494                 attr_merge( e, mod->sm_desc, mod->sm_bvalues ) != 0 ) {
495                 return LDAP_OTHER;
496         }
497
498         return LDAP_SUCCESS;
499 }
500