1 /* mr.c - routines to manage matching rule definitions */
2 /* $OpenLDAP: pkg/ldap/servers/slapd/mr.c,v 1.64.2.3 2008/02/11 23:26:44 kurt Exp $ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2008 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
22 #include <ac/string.h>
23 #include <ac/socket.h>
28 struct berval mir_name
;
32 static Avlnode
*mr_index
= NULL
;
33 static LDAP_SLIST_HEAD(MRList
, MatchingRule
) mr_list
34 = LDAP_SLIST_HEAD_INITIALIZER(&mr_list
);
35 static LDAP_SLIST_HEAD(MRUList
, MatchingRuleUse
) mru_list
36 = LDAP_SLIST_HEAD_INITIALIZER(&mru_list
);
44 const struct mindexrec
*mir1
= v_mir1
;
45 const struct mindexrec
*mir2
= v_mir2
;
46 int i
= mir1
->mir_name
.bv_len
- mir2
->mir_name
.bv_len
;
48 return (strcasecmp( mir1
->mir_name
.bv_val
, mir2
->mir_name
.bv_val
));
57 const struct berval
*name
= v_name
;
58 const struct mindexrec
*mir
= v_mir
;
59 int i
= name
->bv_len
- mir
->mir_name
.bv_len
;
61 return (strncasecmp( name
->bv_val
, mir
->mir_name
.bv_val
, name
->bv_len
));
65 mr_find( const char *mrname
)
69 bv
.bv_val
= (char *)mrname
;
70 bv
.bv_len
= strlen( mrname
);
71 return mr_bvfind( &bv
);
75 mr_bvfind( struct berval
*mrname
)
77 struct mindexrec
*mir
= NULL
;
79 if ( (mir
= avl_find( mr_index
, mrname
, mr_index_name_cmp
)) != NULL
) {
80 return( mir
->mir_mr
);
90 avl_free(mr_index
, ldap_memfree
);
91 while( !LDAP_SLIST_EMPTY(&mr_list
) ) {
92 m
= LDAP_SLIST_FIRST(&mr_list
);
93 LDAP_SLIST_REMOVE_HEAD(&mr_list
, smr_next
);
94 ch_free( m
->smr_str
.bv_val
);
95 ch_free( m
->smr_compat_syntaxes
);
96 ldap_matchingrule_free((LDAPMatchingRule
*)m
);
106 struct mindexrec
*mir
;
109 LDAP_SLIST_NEXT( smr
, smr_next
) = NULL
;
110 LDAP_SLIST_INSERT_HEAD(&mr_list
, smr
, smr_next
);
112 if ( smr
->smr_oid
) {
113 mir
= (struct mindexrec
*)
114 ch_calloc( 1, sizeof(struct mindexrec
) );
115 mir
->mir_name
.bv_val
= smr
->smr_oid
;
116 mir
->mir_name
.bv_len
= strlen( smr
->smr_oid
);
118 if ( avl_insert( &mr_index
, (caddr_t
) mir
,
119 mr_index_cmp
, avl_dup_error
) ) {
122 return SLAP_SCHERR_MR_DUP
;
124 /* FIX: temporal consistency check */
125 mr_bvfind(&mir
->mir_name
);
127 if ( (names
= smr
->smr_names
) ) {
129 mir
= (struct mindexrec
*)
130 ch_calloc( 1, sizeof(struct mindexrec
) );
131 mir
->mir_name
.bv_val
= *names
;
132 mir
->mir_name
.bv_len
= strlen( *names
);
134 if ( avl_insert( &mr_index
, (caddr_t
) mir
,
135 mr_index_cmp
, avl_dup_error
) ) {
138 return SLAP_SCHERR_MR_DUP
;
140 /* FIX: temporal consistency check */
141 mr_bvfind(&mir
->mir_name
);
149 mr_make_syntax_compat_with_mr(
155 assert( syn
!= NULL
);
156 assert( mr
!= NULL
);
158 if ( mr
->smr_compat_syntaxes
) {
161 mr
->smr_compat_syntaxes
[ n
];
164 if ( mr
->smr_compat_syntaxes
[ n
] == syn
) {
165 /* already compatible; mmmmh... */
171 mr
->smr_compat_syntaxes
= ch_realloc(
172 mr
->smr_compat_syntaxes
,
173 sizeof( Syntax
* )*(n
+ 2) );
174 mr
->smr_compat_syntaxes
[ n
] = syn
;
175 mr
->smr_compat_syntaxes
[ n
+ 1 ] = NULL
;
181 mr_make_syntax_compat_with_mrs(
188 assert( syntax
!= NULL
);
189 assert( mrs
!= NULL
);
191 syn
= syn_find( syntax
);
196 for ( r
= 0; mrs
[ r
] != NULL
; r
++ ) {
197 MatchingRule
*mr
= mr_find( mrs
[ r
] );
199 /* matchingRule not found -- ignore by now */
203 rc
+= mr_make_syntax_compat_with_mr( syn
, mr
);
211 LDAPMatchingRule
*mr
,
212 slap_mrule_defs_rec
*def
,
219 Syntax
**compat_syn
= NULL
;
222 if( def
->mrd_compat_syntaxes
) {
224 for( i
=0; def
->mrd_compat_syntaxes
[i
]; i
++ ) {
228 compat_syn
= ch_malloc( sizeof(Syntax
*) * (i
+1) );
230 for( i
=0; def
->mrd_compat_syntaxes
[i
]; i
++ ) {
231 compat_syn
[i
] = syn_find( def
->mrd_compat_syntaxes
[i
] );
232 if( compat_syn
[i
] == NULL
) {
233 ch_free( compat_syn
);
234 return SLAP_SCHERR_SYN_NOT_FOUND
;
238 compat_syn
[i
] = NULL
;
241 smr
= (MatchingRule
*) ch_calloc( 1, sizeof(MatchingRule
) );
242 AC_MEMCPY( &smr
->smr_mrule
, mr
, sizeof(LDAPMatchingRule
));
245 * note: smr_bvoid uses the same memory of smr_mrule.mr_oid;
246 * smr_oidlen is #defined as smr_bvoid.bv_len
248 smr
->smr_bvoid
.bv_val
= smr
->smr_mrule
.mr_oid
;
249 smr
->smr_oidlen
= strlen( mr
->mr_oid
);
250 smr
->smr_usage
= def
->mrd_usage
;
251 smr
->smr_compat_syntaxes
= compat_syn
;
252 smr
->smr_normalize
= def
->mrd_normalize
;
253 smr
->smr_match
= def
->mrd_match
;
254 smr
->smr_indexer
= def
->mrd_indexer
;
255 smr
->smr_filter
= def
->mrd_filter
;
256 smr
->smr_associated
= amr
;
258 if ( smr
->smr_syntax_oid
) {
259 if ( (syn
= syn_find(smr
->smr_syntax_oid
)) ) {
260 smr
->smr_syntax
= syn
;
262 *err
= smr
->smr_syntax_oid
;
264 return SLAP_SCHERR_SYN_NOT_FOUND
;
269 return SLAP_SCHERR_MR_INCOMPLETE
;
271 code
= mr_insert(smr
,err
);
276 register_matching_rule(
277 slap_mrule_defs_rec
*def
)
279 LDAPMatchingRule
*mr
;
280 MatchingRule
*amr
= NULL
;
284 if( def
->mrd_usage
== SLAP_MR_NONE
&& def
->mrd_compat_syntaxes
== NULL
) {
285 Debug( LDAP_DEBUG_ANY
, "register_matching_rule: not usable %s\n",
286 def
->mrd_desc
, 0, 0 );
291 if( def
->mrd_associated
!= NULL
) {
292 amr
= mr_find( def
->mrd_associated
);
294 Debug( LDAP_DEBUG_ANY
, "register_matching_rule: "
295 "could not locate associated matching rule %s for %s\n",
296 def
->mrd_associated
, def
->mrd_desc
, 0 );
301 if (( def
->mrd_usage
& SLAP_MR_EQUALITY
) &&
302 (( def
->mrd_usage
& SLAP_MR_SUBTYPE_MASK
) == SLAP_MR_NONE
))
304 if (( def
->mrd_usage
& SLAP_MR_EQUALITY
) &&
305 (( def
->mrd_usage
& SLAP_MR_SUBTYPE_MASK
) != SLAP_MR_NONE
))
307 Debug( LDAP_DEBUG_ANY
, "register_matching_rule: "
308 "inappropriate (approx) association %s for %s\n",
309 def
->mrd_associated
, def
->mrd_desc
, 0 );
313 } else if (!( amr
->smr_usage
& SLAP_MR_EQUALITY
)) {
314 Debug( LDAP_DEBUG_ANY
, "register_matching_rule: "
315 "inappropriate (equalilty) association %s for %s\n",
316 def
->mrd_associated
, def
->mrd_desc
, 0 );
321 mr
= ldap_str2matchingrule( def
->mrd_desc
, &code
, &err
,
322 LDAP_SCHEMA_ALLOW_ALL
);
324 Debug( LDAP_DEBUG_ANY
,
325 "Error in register_matching_rule: %s before %s in %s\n",
326 ldap_scherr2str(code
), err
, def
->mrd_desc
);
332 code
= mr_add( mr
, def
, amr
, &err
);
337 Debug( LDAP_DEBUG_ANY
,
338 "Error in register_matching_rule: %s for %s in %s\n",
339 scherr2str(code
), err
, def
->mrd_desc
);
352 while( !LDAP_SLIST_EMPTY(&mru_list
) ) {
353 m
= LDAP_SLIST_FIRST(&mru_list
);
354 LDAP_SLIST_REMOVE_HEAD(&mru_list
, smru_next
);
356 if ( m
->smru_str
.bv_val
) {
357 ch_free( m
->smru_str
.bv_val
);
358 m
->smru_str
.bv_val
= NULL
;
360 /* memory borrowed from m->smru_mr */
362 m
->smru_names
= NULL
;
365 /* free what's left (basically smru_mruleuse.mru_applies_oids) */
366 ldap_matchingruleuse_free((LDAPMatchingRuleUse
*)m
);
371 matching_rule_use_init( void )
374 MatchingRuleUse
**mru_ptr
= &LDAP_SLIST_FIRST(&mru_list
);
376 Debug( LDAP_DEBUG_TRACE
, "matching_rule_use_init\n", 0, 0, 0 );
378 LDAP_SLIST_FOREACH( mr
, &mr_list
, smr_next
) {
380 MatchingRuleUse mru_storage
= { 0 },
383 char **applies_oids
= NULL
;
387 /* hide rules marked as HIDE */
388 if ( mr
->smr_usage
& SLAP_MR_HIDE
) {
392 /* hide rules not marked as designed for extensibility */
393 /* MR_EXT means can be used any attribute type whose
394 * syntax is same as the assertion syntax.
395 * Another mechanism is needed where rule can be used
396 * with attribute of other syntaxes.
397 * Framework doesn't support this (yet).
400 if (!( ( mr
->smr_usage
& SLAP_MR_EXT
)
401 || mr
->smr_compat_syntaxes
) )
407 * Note: we're using the same values of the corresponding
408 * MatchingRule structure; maybe we'd copy them ...
411 mru
->smru_obsolete
= mr
->smr_obsolete
;
412 mru
->smru_applies_oids
= NULL
;
413 LDAP_SLIST_NEXT(mru
, smru_next
) = NULL
;
414 mru
->smru_oid
= mr
->smr_oid
;
415 mru
->smru_names
= mr
->smr_names
;
416 mru
->smru_desc
= mr
->smr_desc
;
418 Debug( LDAP_DEBUG_TRACE
, " %s (%s): ",
420 mru
->smru_names
? mru
->smru_names
[ 0 ] : "", 0 );
423 for ( at_start( &at
); at
; at_next( &at
) ) {
424 if( at
->sat_flags
& SLAP_AT_HIDE
) continue;
426 if( mr_usable_with_at( mr
, at
)) {
427 ldap_charray_add( &applies_oids
, at
->sat_cname
.bv_val
);
432 * Note: the matchingRules that are not used
433 * by any attributeType are not listed as
436 if ( applies_oids
!= NULL
) {
437 mru
->smru_applies_oids
= applies_oids
;
439 char *str
= ldap_matchingruleuse2str( &mru
->smru_mruleuse
);
440 Debug( LDAP_DEBUG_TRACE
, "matchingRuleUse: %s\n", str
, 0, 0 );
444 mru
= (MatchingRuleUse
*)ber_memalloc( sizeof( MatchingRuleUse
) );
445 /* call-forward from MatchingRule to MatchingRuleUse */
447 /* copy static data to newly allocated struct */
449 /* append the struct pointer to the end of the list */
451 /* update the list head pointer */
452 mru_ptr
= &LDAP_SLIST_NEXT(mru
,smru_next
);
464 if ( ( mr
->smr_usage
& SLAP_MR_EXT
) && (
465 mr
->smr_syntax
== at
->sat_syntax
||
466 mr
== at
->sat_equality
||
467 mr
== at
->sat_approx
||
468 syn_is_sup( at
->sat_syntax
, mr
->smr_syntax
) ) )
473 if ( mr
->smr_compat_syntaxes
) {
475 for( i
=0; mr
->smr_compat_syntaxes
[i
]; i
++ ) {
476 if( at
->sat_syntax
== mr
->smr_compat_syntaxes
[i
] ) {
484 int mr_schema_info( Entry
*e
)
486 AttributeDescription
*ad_matchingRules
= slap_schema
.si_ad_matchingRules
;
490 LDAP_SLIST_FOREACH(mr
, &mr_list
, smr_next
) {
491 if ( mr
->smr_usage
& SLAP_MR_HIDE
) {
492 /* skip hidden rules */
496 if ( ! mr
->smr_match
) {
497 /* skip rules without matching functions */
501 if ( mr
->smr_str
.bv_val
== NULL
) {
502 if ( ldap_matchingrule2bv( &mr
->smr_mrule
, &mr
->smr_str
) == NULL
) {
507 Debug( LDAP_DEBUG_TRACE
, "Merging mr [%lu] %s\n",
508 mr
->smr_str
.bv_len
, mr
->smr_str
.bv_val
, 0 );
511 nval
.bv_val
= mr
->smr_oid
;
512 nval
.bv_len
= strlen(mr
->smr_oid
);
513 if( attr_merge_one( e
, ad_matchingRules
, &mr
->smr_str
, &nval
) ) {
520 int mru_schema_info( Entry
*e
)
522 AttributeDescription
*ad_matchingRuleUse
523 = slap_schema
.si_ad_matchingRuleUse
;
524 MatchingRuleUse
*mru
;
527 LDAP_SLIST_FOREACH( mru
, &mru_list
, smru_next
) {
528 assert( !( mru
->smru_usage
& SLAP_MR_HIDE
) );
530 if ( mru
->smru_str
.bv_val
== NULL
) {
531 if ( ldap_matchingruleuse2bv( &mru
->smru_mruleuse
, &mru
->smru_str
)
538 Debug( LDAP_DEBUG_TRACE
, "Merging mru [%lu] %s\n",
539 mru
->smru_str
.bv_len
, mru
->smru_str
.bv_val
, 0 );
542 nval
.bv_val
= mru
->smru_oid
;
543 nval
.bv_len
= strlen(mru
->smru_oid
);
544 if( attr_merge_one( e
, ad_matchingRuleUse
, &mru
->smru_str
, &nval
) ) {