]> git.sur5r.net Git - openldap/blob - servers/slapd/back-monitor/log.c
eb7ac6bdbfa04d78bdc5340bc10221cb334e1053
[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 berval           bv[2];
93
94         ldap_pvt_thread_mutex_init( &monitor_log_mutex );
95
96         mi = ( struct monitorinfo * )be->be_private;
97
98         if ( monitor_cache_get( mi, &monitor_subsys[SLAPD_MONITOR_LOG].mss_ndn, 
99                                 &e ) ) {
100 #ifdef NEW_LOGGING
101                 LDAP_LOG(( "operation", LDAP_LEVEL_CRIT,
102                         "monitor_subsys_log_init: "
103                         "unable to get entry '%s'\n",
104                         monitor_subsys[SLAPD_MONITOR_LOG].mss_ndn.bv_val ));
105 #else
106                 Debug( LDAP_DEBUG_ANY,
107                         "monitor_subsys_log_init: "
108                         "unable to get entry '%s'\n%s%s",
109                         monitor_subsys[SLAPD_MONITOR_LOG].mss_ndn.bv_val, 
110                         "", "" );
111 #endif
112                 return( -1 );
113         }
114
115         bv[1].bv_val = NULL;
116
117         /* initialize the debug level */
118         for ( i = 0; int_2_level[ i ].i != 0; i++ ) {
119                 if ( int_2_level[ i ].i & ldap_syslog ) {
120                         bv[0].bv_val = ( char * )int_2_level[ i ].s;
121                         bv[0].bv_len = strlen( bv[0].bv_val );
122
123                         attr_merge( e, monitor_ad_desc, bv );
124                 }
125         }
126
127         monitor_cache_release( mi, e );
128
129         return( 0 );
130 }
131
132 int 
133 monitor_subsys_log_modify( 
134         struct monitorinfo      *mi,
135         Entry                   *e,
136         Modifications           *modlist
137 )
138 {
139         int             rc = LDAP_OTHER;
140         int             newlevel = ldap_syslog;
141         Attribute       *save_attrs;
142         Modifications   *ml;
143
144         ldap_pvt_thread_mutex_lock( &monitor_log_mutex );
145
146         save_attrs = e->e_attrs;
147         e->e_attrs = attrs_dup( e->e_attrs );
148
149         for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
150                 Modification    *mod = &ml->sml_mod;
151
152                 /*
153                  * accept all operational attributes
154                  */
155                 if ( is_at_operational( mod->sm_desc->ad_type ) ) {
156                         ( void ) attr_delete( &e->e_attrs, mod->sm_desc );
157                         rc = attr_merge( e, mod->sm_desc, mod->sm_bvalues );
158                         if ( rc != 0 ) {
159                                 rc = LDAP_OTHER;
160                                 break;
161                         }
162                         continue;
163
164                 /*
165                  * only the monitor description attribute can be modified
166                  */
167                 } else if ( mod->sm_desc != monitor_ad_desc ) {
168                         rc = LDAP_UNWILLING_TO_PERFORM;
169                         break;
170                 }
171
172                 switch ( mod->sm_op ) {
173                 case LDAP_MOD_ADD:
174                         rc = add_values( e, mod, &newlevel );
175                         break;
176                         
177                 case LDAP_MOD_DELETE:
178                         rc = delete_values( e, mod, &newlevel );
179                         break;
180
181                 case LDAP_MOD_REPLACE:
182                         rc = replace_values( e, mod, &newlevel );
183                         break;
184
185                 default:
186                         rc = LDAP_OPERATIONS_ERROR;
187                         break;
188                 }
189
190                 if ( rc != LDAP_SUCCESS ) {
191                         break;
192                 }
193         }
194
195         /* set the new debug level */
196         if ( rc == LDAP_SUCCESS ) {
197                 const char *text;
198                 static char textbuf[1024];
199
200 #if 0   /* need op */
201                 /* check for abandon */
202                 ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
203                 if ( op->o_abandon ) {
204                         ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
205                         rc = SLAPD_ABANDON;
206
207                         goto cleanup;
208                 }
209 #endif
210
211                 /* check that the entry still obeys the schema */
212                 rc = entry_schema_check( e, save_attrs, &text, textbuf, 
213                                 sizeof( textbuf ) );
214                 if ( rc != LDAP_SUCCESS ) {
215                         goto cleanup;
216                 }
217
218                 ldap_syslog = newlevel;
219
220 #if 0   /* debug rather than log */
221                 slap_debug = newlevel;
222                 lutil_set_debug_level( "slapd", slap_debug );
223                 ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &slap_debug);
224                 ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &slap_debug);
225                 ldif_debug = slap_debug;
226 #endif
227         }
228
229 cleanup:;
230         if ( rc == LDAP_SUCCESS ) {
231                 attrs_free( save_attrs );
232
233         } else {
234                 attrs_free( e->e_attrs );
235                 e->e_attrs = save_attrs;
236         }
237         
238         ldap_pvt_thread_mutex_unlock( &monitor_log_mutex );
239
240         return( rc );
241 }
242
243 static int
244 loglevel2int( const char *str )
245 {
246         int             i;
247         
248         for ( i = 0; int_2_level[ i ].i != 0; i++ ) {
249                 if ( strcasecmp( str, int_2_level[ i ].s ) == 0 ) {
250                         return int_2_level[ i ].i;
251                 }
252         }
253
254         return 0;
255 }
256
257 static const char *
258 int2loglevel( int n )
259 {
260         int             i;
261         
262         for ( i = 0; int_2_level[ i ].i != 0; i++ ) {
263                 if ( int_2_level[ i ].i == n ) {
264                         return int_2_level[ i ].s;
265                 }
266         }
267
268         return NULL;
269 }
270
271 static int
272 check_constraints( Modification *mod, int *newlevel )
273 {
274         int             i;
275
276         for ( i = 0; mod->sm_bvalues && mod->sm_bvalues[i].bv_val != NULL; i++ ) {
277                 int l;
278                 const char *s;
279                 ber_len_t len;
280                 
281                 l = loglevel2int( mod->sm_bvalues[i].bv_val );
282                 if ( !l ) {
283                         return LDAP_CONSTRAINT_VIOLATION;
284                 }
285
286                 s = int2loglevel( l );
287                 len = strlen( s );
288                 assert( len == mod->sm_bvalues[i].bv_len );
289                 
290                 AC_MEMCPY( mod->sm_bvalues[i].bv_val, s, len );
291
292                 *newlevel |= l;
293         }
294
295         return LDAP_SUCCESS;
296 }       
297
298 static int 
299 add_values( Entry *e, Modification *mod, int *newlevel )
300 {
301         Attribute       *a;
302         int             i, rc;
303         MatchingRule    *mr = mod->sm_desc->ad_type->sat_equality;
304
305         rc = check_constraints( mod, newlevel );
306         if ( rc != LDAP_SUCCESS ) {
307                 return rc;
308         }
309
310         a = attr_find( e->e_attrs, mod->sm_desc );
311
312         if ( a != NULL ) {
313                 
314                 /* "description" SHOULD have appropriate rules ... */
315                 if ( mr == NULL || !mr->smr_match ) {
316                         return LDAP_INAPPROPRIATE_MATCHING;
317                 }
318
319                 for ( i = 0; mod->sm_bvalues[i].bv_val != NULL; i++ ) {
320                         int rc;
321                         int j;
322                         const char *text = NULL;
323                         struct berval asserted;
324
325                         rc = value_normalize( mod->sm_desc,
326                                         SLAP_MR_EQUALITY,
327                                         &mod->sm_bvalues[i],
328                                         &asserted,
329                                         &text );
330
331                         if ( rc != LDAP_SUCCESS ) {
332                                 return rc;
333                         }
334
335                         for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) {
336                                 int match;
337                                 int rc = value_match( &match, mod->sm_desc, mr,
338                                                 SLAP_MR_VALUE_SYNTAX_MATCH,
339                                                 &a->a_vals[j], &asserted, &text );
340
341                                 if ( rc == LDAP_SUCCESS && match == 0 ) {
342                                         free( asserted.bv_val );
343                                         return LDAP_TYPE_OR_VALUE_EXISTS;
344                                 }
345                         }
346
347                         free( asserted.bv_val );
348                 }
349         }
350
351         /* no - add them */
352         if ( attr_merge( e, mod->sm_desc, mod->sm_bvalues ) != 0 ) {
353                 /* this should return result of attr_merge */
354                 return LDAP_OTHER;
355         }
356
357         return LDAP_SUCCESS;
358 }
359
360 static int
361 delete_values( Entry *e, Modification *mod, int *newlevel )
362 {
363         int             i, j, k, found, rc, nl = 0;
364         Attribute       *a;
365         MatchingRule    *mr = mod->sm_desc->ad_type->sat_equality;
366
367         rc = check_constraints( mod, &nl );
368         if ( rc != LDAP_SUCCESS ) {
369                 return rc;
370         }
371
372         *newlevel &= ~nl;
373
374         /* delete the entire attribute */
375         if ( mod->sm_bvalues == NULL ) {
376                 int rc = attr_delete( &e->e_attrs, mod->sm_desc );
377
378                 if ( rc ) {
379                         rc = LDAP_NO_SUCH_ATTRIBUTE;
380                 } else {
381                         *newlevel = 0;
382                         rc = LDAP_SUCCESS;
383                 }
384                 return rc;
385         }
386
387         if ( mr == NULL || !mr->smr_match ) {
388                 /* disallow specific attributes from being deleted if
389                  * no equality rule */
390                 return LDAP_INAPPROPRIATE_MATCHING;
391         }
392
393         /* delete specific values - find the attribute first */
394         if ( (a = attr_find( e->e_attrs, mod->sm_desc )) == NULL ) {
395                 return( LDAP_NO_SUCH_ATTRIBUTE );
396         }
397
398         /* find each value to delete */
399         for ( i = 0; mod->sm_bvalues[i].bv_val != NULL; i++ ) {
400                 int rc;
401                 const char *text = NULL;
402
403                 struct berval asserted;
404
405                 rc = value_normalize( mod->sm_desc,
406                                 SLAP_MR_EQUALITY,
407                                 &mod->sm_bvalues[i],
408                                 &asserted,
409                                 &text );
410
411                 if( rc != LDAP_SUCCESS ) return rc;
412
413                 found = 0;
414                 for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) {
415                         int match;
416                         int rc = value_match( &match, mod->sm_desc, mr,
417                                         SLAP_MR_VALUE_SYNTAX_MATCH,
418                                         &a->a_vals[j], &asserted, &text );
419
420                         if( rc == LDAP_SUCCESS && match != 0 ) {
421                                 continue;
422                         }
423
424                         /* found a matching value */
425                         found = 1;
426
427                         /* delete it */
428                         free( a->a_vals[j].bv_val );
429                         for ( k = j + 1; a->a_vals[k].bv_val != NULL; k++ ) {
430                                 a->a_vals[k - 1] = a->a_vals[k];
431                         }
432                         a->a_vals[k - 1].bv_val = NULL;
433
434                         break;
435                 }
436
437                 free( asserted.bv_val );
438
439                 /* looked through them all w/o finding it */
440                 if ( ! found ) {
441                         return LDAP_NO_SUCH_ATTRIBUTE;
442                 }
443         }
444
445         /* if no values remain, delete the entire attribute */
446         if ( a->a_vals[0].bv_val == NULL ) {
447                 /* should already be zero */
448                 *newlevel = 0;
449                 
450                 if ( attr_delete( &e->e_attrs, mod->sm_desc ) ) {
451                         return LDAP_NO_SUCH_ATTRIBUTE;
452                 }
453         }
454
455         return LDAP_SUCCESS;
456 }
457
458 static int
459 replace_values( Entry *e, Modification *mod, int *newlevel )
460 {
461         int rc;
462
463         *newlevel = 0;
464         rc = check_constraints( mod, newlevel );
465         if ( rc != LDAP_SUCCESS ) {
466                 return rc;
467         }
468
469         rc = attr_delete( &e->e_attrs, mod->sm_desc );
470
471         if ( rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_ATTRIBUTE ) {
472                 return rc;
473         }
474
475         if ( mod->sm_bvalues != NULL &&
476                 attr_merge( e, mod->sm_desc, mod->sm_bvalues ) != 0 ) {
477                 return LDAP_OTHER;
478         }
479
480         return LDAP_SUCCESS;
481 }
482