]> git.sur5r.net Git - openldap/blob - servers/slapd/back-monitor/log.c
Happy new year
[openldap] / servers / slapd / back-monitor / log.c
1 /* log.c - deal with log subsystem */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2001-2004 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
26 #include <ac/string.h>
27
28 #include "slap.h"
29 #include <lber_pvt.h>
30 #include "lutil.h"
31 #include "ldif.h"
32 #include "back-monitor.h"
33
34 /*
35  * log mutex
36  */
37 ldap_pvt_thread_mutex_t         monitor_log_mutex;
38
39 static struct {
40         int i;
41         struct berval s;
42         struct berval n;
43 } int_2_level[] = {
44         { LDAP_DEBUG_TRACE,     BER_BVC("Trace"),       { 0, NULL } },
45         { LDAP_DEBUG_PACKETS,   BER_BVC("Packets"),     { 0, NULL } },
46         { LDAP_DEBUG_ARGS,      BER_BVC("Args"),        { 0, NULL } },
47         { LDAP_DEBUG_CONNS,     BER_BVC("Conns"),       { 0, NULL } },
48         { LDAP_DEBUG_BER,       BER_BVC("BER"), { 0, NULL } },
49         { LDAP_DEBUG_FILTER,    BER_BVC("Filter"),      { 0, NULL } },
50         { LDAP_DEBUG_CONFIG,    BER_BVC("Config"),      { 0, NULL } },  /* useless */
51         { LDAP_DEBUG_ACL,       BER_BVC("ACL"), { 0, NULL } },
52         { LDAP_DEBUG_STATS,     BER_BVC("Stats"),       { 0, NULL } },
53         { LDAP_DEBUG_STATS2,    BER_BVC("Stats2"),      { 0, NULL } },
54         { LDAP_DEBUG_SHELL,     BER_BVC("Shell"),       { 0, NULL } },
55         { LDAP_DEBUG_PARSE,     BER_BVC("Parse"),       { 0, NULL } },
56         { LDAP_DEBUG_CACHE,     BER_BVC("Cache"),       { 0, NULL } },
57         { LDAP_DEBUG_INDEX,     BER_BVC("Index"),       { 0, NULL } },
58         { 0,                    { 0, NULL },    { 0, NULL } }
59 };
60
61 static int loglevel2int( struct berval *l );
62 static int int2loglevel( int n );
63
64 static int add_values( Entry *e, Modification *mod, int *newlevel );
65 static int delete_values( Entry *e, Modification *mod, int *newlevel );
66 static int replace_values( Entry *e, Modification *mod, int *newlevel );
67
68 /*
69  * initializes log subentry
70  */
71 int
72 monitor_subsys_log_init(
73         BackendDB       *be
74 )
75 {
76         struct monitorinfo      *mi;
77         Entry                   *e;
78         int                     i;
79         struct berval           desc[] = {
80                 BER_BVC("This entry allows to set the log level runtime."),
81                 BER_BVC("Set the attribute 'managedInfo' to the desired log levels."),
82                 { 0, NULL }
83         };
84
85         ldap_pvt_thread_mutex_init( &monitor_log_mutex );
86
87         mi = ( struct monitorinfo * )be->be_private;
88
89         if ( monitor_cache_get( mi, &monitor_subsys[SLAPD_MONITOR_LOG].mss_ndn, 
90                                 &e ) ) {
91 #ifdef NEW_LOGGING
92                 LDAP_LOG( OPERATION, CRIT,
93                         "monitor_subsys_log_init: "
94                         "unable to get entry '%s'\n",
95                         monitor_subsys[SLAPD_MONITOR_LOG].mss_ndn.bv_val, 0, 0 );
96 #else
97                 Debug( LDAP_DEBUG_ANY,
98                         "monitor_subsys_log_init: "
99                         "unable to get entry '%s'\n%s%s",
100                         monitor_subsys[SLAPD_MONITOR_LOG].mss_ndn.bv_val, 
101                         "", "" );
102 #endif
103                 return( -1 );
104         }
105
106         /* initialize the debug level(s) */
107         for ( i = 0; int_2_level[ i ].i != 0; i++ ) {
108
109                 if ( mi->mi_ad_managedInfo->ad_type->sat_equality->smr_normalize ) {
110                         int     rc;
111
112                         rc = (*mi->mi_ad_managedInfo->ad_type->sat_equality->smr_normalize)(
113                                         SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
114                                         mi->mi_ad_managedInfo->ad_type->sat_syntax,
115                                         mi->mi_ad_managedInfo->ad_type->sat_equality,
116                                         &int_2_level[ i ].s,
117                                         &int_2_level[ i ].n, NULL );
118                         if ( rc ) {
119                                 return( -1 );
120                         }
121                 }
122
123                 if ( int_2_level[ i ].i & ldap_syslog ) {
124                         attr_merge_one( e, mi->mi_ad_managedInfo,
125                                         &int_2_level[ i ].s,
126                                         &int_2_level[ i ].n );
127                 }
128         }
129
130         attr_merge( e, mi->mi_ad_description, desc, NULL );
131
132         monitor_cache_release( mi, e );
133
134         return( 0 );
135 }
136
137 int 
138 monitor_subsys_log_modify( 
139         Operation               *op,
140         Entry                   *e
141 )
142 {
143         struct monitorinfo *mi = (struct monitorinfo *)op->o_bd->be_private;
144         int             rc = LDAP_OTHER;
145         int             newlevel = ldap_syslog;
146         Attribute       *save_attrs;
147         Modifications   *modlist = op->oq_modify.rs_modlist;
148         Modifications   *ml;
149
150         ldap_pvt_thread_mutex_lock( &monitor_log_mutex );
151
152         save_attrs = e->e_attrs;
153         e->e_attrs = attrs_dup( e->e_attrs );
154
155         for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
156                 Modification    *mod = &ml->sml_mod;
157
158                 /*
159                  * accept all operational attributes
160                  */
161                 if ( is_at_operational( mod->sm_desc->ad_type ) ) {
162                         ( void ) attr_delete( &e->e_attrs, mod->sm_desc );
163                         rc = attr_merge( e, mod->sm_desc, mod->sm_bvalues,
164                                         mod->sm_nvalues );
165                         if ( rc != 0 ) {
166                                 rc = LDAP_OTHER;
167                                 break;
168                         }
169                         continue;
170
171                 /*
172                  * only the monitor description attribute can be modified
173                  */
174                 } else if ( mod->sm_desc != mi->mi_ad_managedInfo) {
175                         rc = LDAP_UNWILLING_TO_PERFORM;
176                         break;
177                 }
178
179                 switch ( mod->sm_op ) {
180                 case LDAP_MOD_ADD:
181                         rc = add_values( e, mod, &newlevel );
182                         break;
183                         
184                 case LDAP_MOD_DELETE:
185                         rc = delete_values( e, mod, &newlevel );
186                         break;
187
188                 case LDAP_MOD_REPLACE:
189                         rc = replace_values( e, mod, &newlevel );
190                         break;
191
192                 default:
193                         rc = LDAP_OTHER;
194                         break;
195                 }
196
197                 if ( rc != LDAP_SUCCESS ) {
198                         break;
199                 }
200         }
201
202         /* set the new debug level */
203         if ( rc == LDAP_SUCCESS ) {
204                 const char      *text;
205                 static char     textbuf[ BACKMONITOR_BUFSIZE ];
206
207                 /* check for abandon */
208                 if ( op->o_abandon ) {
209                         rc = SLAPD_ABANDON;
210
211                         goto cleanup;
212                 }
213
214                 /* check that the entry still obeys the schema */
215                 rc = entry_schema_check( be_monitor, e, save_attrs, 
216                                 &text, textbuf, sizeof( textbuf ) );
217                 if ( rc != LDAP_SUCCESS ) {
218                         goto cleanup;
219                 }
220
221                 /*
222                  * Do we need to protect this with a mutex?
223                  */
224                 ldap_syslog = newlevel;
225
226 #if 0   /* debug rather than log */
227                 slap_debug = newlevel;
228                 lutil_set_debug_level( "slapd", slap_debug );
229                 ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &slap_debug);
230                 ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &slap_debug);
231                 ldif_debug = slap_debug;
232 #endif
233         }
234
235 cleanup:;
236         if ( rc == LDAP_SUCCESS ) {
237                 attrs_free( save_attrs );
238
239         } else {
240                 attrs_free( e->e_attrs );
241                 e->e_attrs = save_attrs;
242         }
243         
244         ldap_pvt_thread_mutex_unlock( &monitor_log_mutex );
245
246         return( rc );
247 }
248
249 static int
250 loglevel2int( struct berval *l )
251 {
252         int             i;
253         
254         for ( i = 0; int_2_level[ i ].i != 0; i++ ) {
255                 if ( l->bv_len != int_2_level[ i ].s.bv_len ) {
256                         continue;
257                 }
258
259                 if ( strcasecmp( l->bv_val, int_2_level[ i ].s.bv_val ) == 0 ) {
260                         return int_2_level[ i ].i;
261                 }
262         }
263
264         return 0;
265 }
266
267 static int
268 int2loglevel( int n )
269 {
270         int             i;
271         
272         for ( i = 0; int_2_level[ i ].i != 0; i++ ) {
273                 if ( int_2_level[ i ].i == n ) {
274                         return i;
275                 }
276         }
277
278         return -1;
279 }
280
281 static int
282 check_constraints( Modification *mod, int *newlevel )
283 {
284         int             i;
285
286         for ( i = 0; mod->sm_bvalues && mod->sm_bvalues[i].bv_val != NULL; i++ ) {
287                 int             l;
288                 
289                 l = loglevel2int( &mod->sm_bvalues[i] );
290                 if ( !l ) {
291                         return LDAP_CONSTRAINT_VIOLATION;
292                 }
293
294                 if ( ( l = int2loglevel( l ) ) == -1 ) {
295                         return LDAP_OTHER;
296                 }
297
298                 assert( int_2_level[ l ].s.bv_len
299                                 == mod->sm_bvalues[i].bv_len );
300                 
301                 AC_MEMCPY( mod->sm_bvalues[i].bv_val,
302                                 int_2_level[ l ].s.bv_val,
303                                 int_2_level[ l ].s.bv_len );
304
305                 AC_MEMCPY( mod->sm_nvalues[i].bv_val,
306                                 int_2_level[ l ].n.bv_val,
307                                 int_2_level[ l ].n.bv_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                 /* "description" SHOULD have appropriate rules ... */
331                 if ( mr == NULL || !mr->smr_match ) {
332                         return LDAP_INAPPROPRIATE_MATCHING;
333                 }
334
335                 for ( i = 0; mod->sm_bvalues[i].bv_val != NULL; i++ ) {
336                         int rc;
337                         int j;
338                         const char *text = NULL;
339                         struct berval asserted;
340
341                         rc = asserted_value_validate_normalize(
342                                 mod->sm_desc, mr, SLAP_MR_EQUALITY,
343                                 &mod->sm_bvalues[i], &asserted, &text, NULL );
344
345                         if ( rc != LDAP_SUCCESS ) {
346                                 return rc;
347                         }
348
349                         for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) {
350                                 int match;
351                                 int rc = value_match( &match, mod->sm_desc, mr,
352                                         0,
353                                         &a->a_vals[j], &asserted, &text );
354
355                                 if ( rc == LDAP_SUCCESS && match == 0 ) {
356                                         free( asserted.bv_val );
357                                         return LDAP_TYPE_OR_VALUE_EXISTS;
358                                 }
359                         }
360
361                         free( asserted.bv_val );
362                 }
363         }
364
365         /* no - add them */
366         rc = attr_merge( e, mod->sm_desc, mod->sm_bvalues, mod->sm_nvalues );
367         if ( rc != LDAP_SUCCESS ) {
368                 /* this should return result of attr_mergeit */
369                 return rc;
370         }
371
372         return LDAP_SUCCESS;
373 }
374
375 static int
376 delete_values( Entry *e, Modification *mod, int *newlevel )
377 {
378         int             i, j, k, found, rc, nl = 0;
379         Attribute       *a;
380         MatchingRule    *mr = mod->sm_desc->ad_type->sat_equality;
381
382         rc = check_constraints( mod, &nl );
383         if ( rc != LDAP_SUCCESS ) {
384                 return rc;
385         }
386
387         *newlevel &= ~nl;
388
389         /* delete the entire attribute */
390         if ( mod->sm_bvalues == NULL ) {
391                 int rc = attr_delete( &e->e_attrs, mod->sm_desc );
392
393                 if ( rc ) {
394                         rc = LDAP_NO_SUCH_ATTRIBUTE;
395                 } else {
396                         *newlevel = 0;
397                         rc = LDAP_SUCCESS;
398                 }
399                 return rc;
400         }
401
402         if ( mr == NULL || !mr->smr_match ) {
403                 /* disallow specific attributes from being deleted if
404                  * no equality rule */
405                 return LDAP_INAPPROPRIATE_MATCHING;
406         }
407
408         /* delete specific values - find the attribute first */
409         if ( (a = attr_find( e->e_attrs, mod->sm_desc )) == NULL ) {
410                 return( LDAP_NO_SUCH_ATTRIBUTE );
411         }
412
413         /* find each value to delete */
414         for ( i = 0; mod->sm_bvalues[i].bv_val != NULL; i++ ) {
415                 int rc;
416                 const char *text = NULL;
417
418                 struct berval asserted;
419
420                 rc = asserted_value_validate_normalize(
421                                 mod->sm_desc, mr, SLAP_MR_EQUALITY,
422                                 &mod->sm_bvalues[i], &asserted, &text, NULL );
423
424                 if( rc != LDAP_SUCCESS ) return rc;
425
426                 found = 0;
427                 for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) {
428                         int match;
429                         int rc = value_match( &match, mod->sm_desc, mr,
430                                 0,
431                                 &a->a_vals[j], &asserted, &text );
432
433                         if( rc == LDAP_SUCCESS && match != 0 ) {
434                                 continue;
435                         }
436
437                         /* found a matching value */
438                         found = 1;
439
440                         /* delete it */
441                         free( a->a_vals[j].bv_val );
442                         for ( k = j + 1; a->a_vals[k].bv_val != NULL; k++ ) {
443                                 a->a_vals[k - 1] = a->a_vals[k];
444                         }
445                         a->a_vals[k - 1].bv_val = NULL;
446
447                         break;
448                 }
449
450                 free( asserted.bv_val );
451
452                 /* looked through them all w/o finding it */
453                 if ( ! found ) {
454                         return LDAP_NO_SUCH_ATTRIBUTE;
455                 }
456         }
457
458         /* if no values remain, delete the entire attribute */
459         if ( a->a_vals[0].bv_val == NULL ) {
460                 /* should already be zero */
461                 *newlevel = 0;
462                 
463                 if ( attr_delete( &e->e_attrs, mod->sm_desc ) ) {
464                         return LDAP_NO_SUCH_ATTRIBUTE;
465                 }
466         }
467
468         return LDAP_SUCCESS;
469 }
470
471 static int
472 replace_values( Entry *e, Modification *mod, int *newlevel )
473 {
474         int rc;
475
476         *newlevel = 0;
477         rc = check_constraints( mod, newlevel );
478         if ( rc != LDAP_SUCCESS ) {
479                 return rc;
480         }
481
482         rc = attr_delete( &e->e_attrs, mod->sm_desc );
483
484         if ( rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_ATTRIBUTE ) {
485                 return rc;
486         }
487
488         if ( mod->sm_bvalues != NULL ) {
489                 rc = attr_merge( e, mod->sm_desc, mod->sm_bvalues,
490                        mod->sm_nvalues );
491                 if ( rc != LDAP_SUCCESS ) {
492                         return rc;
493                 }
494         }
495
496         return LDAP_SUCCESS;
497 }
498