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