+ if ( is_at_obsolete( ad->ad_type ) &&
+ ( ml->sml_op == LDAP_MOD_ADD || ml->sml_bvalues != NULL ) )
+ {
+ /*
+ * attribute is obsolete,
+ * only allow replace/delete with no values
+ */
+ snprintf( textbuf, textlen,
+ "%s: attribute is obsolete",
+ ml->sml_type.bv_val );
+ *text = textbuf;
+ return LDAP_CONSTRAINT_VIOLATION;
+ }
+
+ /*
+ * check values
+ */
+ if( ml->sml_bvalues != NULL ) {
+ ber_len_t nvals;
+ slap_syntax_validate_func *validate =
+ ad->ad_type->sat_syntax->ssyn_validate;
+ slap_syntax_transform_func *pretty =
+ ad->ad_type->sat_syntax->ssyn_pretty;
+
+ if( !pretty && !validate ) {
+ *text = "no validator for syntax";
+ snprintf( textbuf, textlen,
+ "%s: no validator for syntax %s",
+ ml->sml_type.bv_val,
+ ad->ad_type->sat_syntax->ssyn_oid );
+ *text = textbuf;
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ /*
+ * check that each value is valid per syntax
+ * and pretty if appropriate
+ */
+ for( nvals = 0; ml->sml_bvalues[nvals].bv_val; nvals++ ) {
+ struct berval pval;
+ if( pretty ) {
+ rc = pretty( ad->ad_type->sat_syntax,
+ &ml->sml_bvalues[nvals], &pval );
+ } else {
+ rc = validate( ad->ad_type->sat_syntax,
+ &ml->sml_bvalues[nvals] );
+ }
+
+ if( rc != 0 ) {
+ snprintf( textbuf, textlen,
+ "%s: value #%ld invalid per syntax",
+ ml->sml_type.bv_val, (long) nvals );
+ *text = textbuf;
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ if( pretty ) {
+ ber_memfree( ml->sml_bvalues[nvals].bv_val );
+ ml->sml_bvalues[nvals] = pval;
+ }
+ }
+
+ /*
+ * a rough single value check... an additional check is needed
+ * to catch add of single value to existing single valued attribute
+ */
+ if( ( ml->sml_op == LDAP_MOD_ADD || ml->sml_op == LDAP_MOD_REPLACE )
+ && nvals > 1 && is_at_single_value( ad->ad_type ))
+ {
+ snprintf( textbuf, textlen,
+ "%s: multiple value provided",
+ ml->sml_type.bv_val );
+ *text = textbuf;
+ return LDAP_CONSTRAINT_VIOLATION;
+ }
+ }