+ /* Do we have too many timestamps? If so, delete some values.
+ * We don't bother to sort the values here. OpenLDAP keeps the
+ * values in order by default. Fundamentally, relying on the
+ * information here is wrong anyway; monitoring systems should
+ * be tracking Bind failures in syslog, not here.
+ */
+ if (a->a_numvals >= ppb->pp.pwdMaxRecordedFailure) {
+ int j = ppb->pp.pwdMaxRecordedFailure-1;
+ /* If more than 2x, cheaper to perform a Replace */
+ if (a->a_numvals >= 2 * ppb->pp.pwdMaxRecordedFailure) {
+ struct berval v, nv;
+
+ /* Change the mod we constructed above */
+ m->sml_op = LDAP_MOD_REPLACE;
+ m->sml_numvals = ppb->pp.pwdMaxRecordedFailure;
+ v = m->sml_values[0];
+ nv = m->sml_nvalues[0];
+ ch_free(m->sml_values);
+ ch_free(m->sml_nvalues);
+ m->sml_values = ch_calloc( sizeof(struct berval), ppb->pp.pwdMaxRecordedFailure+1 );
+ m->sml_nvalues = ch_calloc( sizeof(struct berval), ppb->pp.pwdMaxRecordedFailure+1 );
+ for (i=0; i<j; i++) {
+ ber_dupbv(&m->sml_values[i], &a->a_vals[a->a_numvals-j+i]);
+ ber_dupbv(&m->sml_nvalues[i], &a->a_nvals[a->a_numvals-j+i]);
+ }
+ m->sml_values[i] = v;
+ m->sml_nvalues[i] = nv;
+ } else {
+ /* else just delete some */
+ m = ch_calloc( sizeof(Modifications), 1 );
+ m->sml_op = LDAP_MOD_DELETE;
+ m->sml_type = ad_pwdFailureTime->ad_cname;
+ m->sml_desc = ad_pwdFailureTime;
+ m->sml_numvals = a->a_numvals - j;
+ m->sml_values = ch_calloc( sizeof(struct berval), m->sml_numvals+1 );
+ m->sml_nvalues = ch_calloc( sizeof(struct berval), m->sml_numvals+1 );
+ for (i=0; i<m->sml_numvals; i++) {
+ ber_dupbv(&m->sml_values[i], &a->a_vals[i]);
+ ber_dupbv(&m->sml_nvalues[i], &a->a_nvals[i]);
+ }
+ m->sml_next = mod;
+ mod = m;
+ }
+ }