]> git.sur5r.net Git - openldap/blob - servers/slapd/limits.c
add global, per backend and per op_ndn time/size soft, hard and to-be-checked limits...
[openldap] / servers / slapd / limits.c
1 /* limits.c - routines to handle regex-based size and time limits */
2 /*
3  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6
7 #include "portable.h"
8
9 #include <stdio.h>
10
11 #include <ac/regex.h>
12 #include <ac/string.h>
13
14 #include "slap.h"
15
16 int
17 get_limits( 
18         Backend                 *be, 
19         const char              *ndn, 
20         struct slap_limits_set  **limit
21 )
22 {
23         struct slap_limits **lm;
24
25         assert( be );
26         assert( limit );
27
28         /*
29          * default values
30          */
31         *limit = &be->be_def_limit;
32
33         /*
34          * anonymous or no regex-based limits? 
35          */
36         if ( be->be_limits == NULL || ndn == NULL || ndn[0] == '\0' ) {
37                 return( 0 );
38         }
39
40         for ( lm = be->be_limits; lm[0] != NULL; lm++ ) {
41                 switch ( lm[0]->lm_type) {
42                 case SLAP_LIMITS_EXACT:
43                         if ( strcmp( lm[0]->lm_dn_pat, ndn ) == 0 ) {
44                                 *limit = &lm[0]->lm_limits;
45                                 return( 0 );
46                         }
47                         break;
48
49                 case SLAP_LIMITS_REGEX:
50                         if ( regexec( &lm[0]->lm_dn_regex, ndn, 0, NULL, 0) == 0 ) {
51                                 *limit = &lm[0]->lm_limits;
52                                 return( 0 );
53                         }
54                         break;
55                         
56                 default:
57                         assert( 0 );    /* unreachable */
58                         return( -1 );
59                 }
60         }
61
62         return( 0 );
63 }
64
65 int
66 add_limits(
67         Backend                 *be,
68         int                     type,
69         const char              *pattern,
70         struct slap_limits_set  *limit
71 )
72 {
73         int                     i;
74         struct slap_limits      *lm;
75         
76         assert( be );
77         assert( pattern );
78         assert( limit );
79
80         lm = ( struct slap_limits * )ch_calloc( sizeof( struct slap_limits ), 1 );
81
82         switch ( type ) {
83         case SLAP_LIMITS_EXACT:
84                 lm->lm_type = SLAP_LIMITS_EXACT;
85                 lm->lm_dn_pat = ch_strdup( pattern );
86                 if ( dn_normalize( lm->lm_dn_pat ) == NULL ) {
87                         ch_free( lm->lm_dn_pat );
88                         ch_free( lm );
89                         return( -1 );
90                 }
91                 break;
92                 
93         case SLAP_LIMITS_REGEX:
94         case SLAP_LIMITS_UNDEFINED:
95                 lm->lm_type = SLAP_LIMITS_REGEX;
96                 lm->lm_dn_pat = ch_strdup( pattern );
97                 if ( regcomp( &lm->lm_dn_regex, lm->lm_dn_pat, REG_EXTENDED | REG_ICASE ) ) {
98                         ch_free( lm->lm_dn_pat );
99                         ch_free( lm );
100                         return( -1 );
101                 }
102                 break;
103         }
104
105         lm->lm_limits = *limit;
106
107         i = 0;
108         if ( be->be_limits != NULL ) {
109                 for ( ; be->be_limits[i]; i++ );
110         }
111
112         be->be_limits = ( struct slap_limits ** )ch_realloc( be->be_limits,
113                         sizeof( struct slap_limits * ) * ( i + 2 ) );
114         be->be_limits[i] = lm;
115         be->be_limits[i+1] = NULL;
116         
117         return( 0 );
118 }
119
120 int
121 parse_limits(
122         Backend     *be,
123         const char  *fname,
124         int         lineno,
125         int         argc,
126         char        **argv
127 )
128 {
129         int     type = SLAP_LIMITS_UNDEFINED;
130         char    *pattern;
131         struct slap_limits_set limit;
132         int     i;
133
134         assert( be );
135
136         if ( argc < 3 ) {
137 #ifdef NEW_LOGGING
138                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
139                         "%s : line %d: missing arg(s) in "
140                         "\"limits <pattern> <limits>\" line.\n",
141                         fname, lineno ));
142 #else
143                 Debug( LDAP_DEBUG_ANY,
144                         "%s : line %d: missing arg(s) in "
145                         "\"limits <pattern> <limits>\" line.\n%s",
146                         fname, lineno, "" );
147 #endif
148                 return( -1 );
149         }
150
151         limit = be->be_def_limit;
152
153         /*
154          * syntax:
155          *
156          * "limits" <pattern> <limit> [ ... ]
157          * 
158          * 
159          * <pattern>:
160          * 
161          * [ "dn" [ "." { "exact" | "regex" } ] "=" ] <dn pattern>
162          *
163          * 
164          * <limit>:
165          *
166          * "time" [ "." { "soft" | "hard" } ] "=" <integer>
167          *
168          * "size" [ "." { "soft" | "hard" | "unchecked" } ] "=" <integer>
169          */
170         
171         pattern = argv[1];
172         if ( strncasecmp( pattern, "dn", 2 ) == 0 ) {
173                 pattern += 2;
174                 if ( pattern[0] == '.' ) {
175                         pattern++;
176                         if ( strncasecmp( pattern, "exact", 5 ) == 0 ) {
177                                 type = SLAP_LIMITS_EXACT;
178                                 pattern += 5;
179                         } else if ( strncasecmp( pattern, "regex", 5 ) == 0 ) {
180                                 type = SLAP_LIMITS_REGEX;
181                                 pattern += 5;
182                         }
183                 }
184
185                 if ( pattern[0] != '=' ) {
186 #ifdef NEW_LOGGING
187                         LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
188                                 "%s : line %d: missing '=' in "
189                                 "\"dn[.{exact|regex}]=<pattern>\" in "
190                                 "\"limits <pattern> <limits>\" line.\n",
191                         fname, lineno ));
192 #else
193                         Debug( LDAP_DEBUG_ANY,
194                                 "%s : line %d: missing '=' in "
195                                 "\"dn[.{exact|regex}]=<pattern>\" in "
196                                 "\"limits <pattern> <limits>\" line.\n%s",
197                         fname, lineno, "" );
198 #endif
199                         return( -1 );
200                 }
201
202                 /* skip '=' (required) */
203                 pattern++;
204         }
205
206         for ( i = 2; i < argc; i++ ) {
207                 if ( parse_limit( argv[i], &limit ) ) {
208
209 #ifdef NEW_LOGGING
210                         LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
211                                 "%s : line %d: unknown limit type \"%s\" in "
212                                 "\"limits <pattern> <limits>\" line.\n",
213                         fname, lineno, argv[i] ));
214 #else
215                         Debug( LDAP_DEBUG_ANY,
216                                 "%s : line %d: unknown limit type \"%s\" in "
217                                 "\"limits <pattern> <limits>\" line.\n",
218                         fname, lineno, argv[i] );
219 #endif
220
221                         return( 1 );
222                 }
223         }
224
225         /*
226          * sanity checks ...
227          */
228         if ( limit.lms_t_hard > 0 && limit.lms_t_hard < limit.lms_t_soft ) {
229                 limit.lms_t_hard = limit.lms_t_soft;
230         }
231         
232         if ( limit.lms_s_hard > 0 && limit.lms_s_hard < limit.lms_s_soft ) {
233                 limit.lms_s_hard = limit.lms_s_soft;
234         }
235         
236         return( add_limits( be, type, pattern, &limit ) );
237 }
238
239 int
240 parse_limit(
241         const char              *arg,
242         struct slap_limits_set  *limit
243 )
244 {
245         assert( arg );
246         assert( limit );
247
248         if ( strncasecmp( arg, "time", 4 ) == 0 ) {
249                 arg += 4;
250
251                 if ( arg[0] == '.' ) {
252                         arg++;
253                         if ( strncasecmp( arg, "soft", 4 ) == 0 ) {
254                                 arg += 4;
255                                 if ( arg[0] != '=' ) {
256                                         return( 1 );
257                                 }
258                                 arg++;
259                                 limit->lms_t_soft = atoi( arg );
260                                 
261                         } else if ( strncasecmp( arg, "hard", 4 ) == 0 ) {
262                                 arg += 4;
263                                 if ( arg[0] != '=' ) {
264                                         return( 1 );
265                                 }
266                                 arg++;
267                                 limit->lms_t_hard = atoi( arg );
268                                 
269                         } else {
270                                 return( 1 );
271                         }
272                         
273                 } else if ( arg[0] == '=' ) {
274                         limit->lms_t_soft = atoi( arg );
275                         limit->lms_t_hard = 0;
276                         
277                 } else {
278                         return( 1 );
279                 }
280
281         } else if ( strncasecmp( arg, "size", 4 ) == 0 ) {
282                 arg += 4;
283                 
284                 if ( arg[0] == '.' ) {
285                         arg++;
286                         if ( strncasecmp( arg, "soft", 4 ) == 0 ) {
287                                 arg += 4;
288                                 if ( arg[0] != '=' ) {
289                                         return( 1 );
290                                 }
291                                 arg++;
292                                 limit->lms_s_soft = atoi( arg );
293                                 
294                         } else if ( strncasecmp( arg, "hard", 4 ) == 0 ) {
295                                 arg += 4;
296                                 if ( arg[0] != '=' ) {
297                                         return( 1 );
298                                 }
299                                 arg++;
300                                 limit->lms_s_hard = atoi( arg );
301                                 
302                         } else if ( strncasecmp( arg, "unchecked", 9 ) == 0 ) {
303                                 arg += 9;
304                                 if ( arg[0] != '=' ) {
305                                         return( 1 );
306                                 }
307                                 arg++;
308                                 limit->lms_s_unchecked = atoi( arg );
309                                 
310                         } else {
311                                 return( 1 );
312                         }
313                         
314                 } else if ( arg[0] == '=' ) {
315                         limit->lms_s_soft = atoi( arg );
316                         limit->lms_s_hard = 0;
317                         
318                 } else {
319                         return( 1 );
320                 }
321         }
322
323         return 0;
324 }
325