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