+
+int
+slap_ctrl_session_tracking_add(
+ Operation *op,
+ SlapReply *rs,
+ struct berval *ip,
+ struct berval *name,
+ struct berval *id,
+ LDAPControl *ctrl )
+{
+ BerElementBuffer berbuf;
+ BerElement *ber = (BerElement *)&berbuf;
+
+ static struct berval oid = BER_BVC( LDAP_CONTROL_X_SESSION_TRACKING_USERNAME );
+
+ assert( ctrl != NULL );
+
+ ber_init2( ber, NULL, LBER_USE_DER );
+
+ ber_printf( ber, "{OOOO}", ip, name, &oid, id );
+
+ if ( ber_flatten2( ber, &ctrl->ldctl_value, 0 ) == -1 ) {
+ rs->sr_err = LDAP_OTHER;
+ goto done;
+ }
+
+ ctrl->ldctl_oid = LDAP_CONTROL_X_SESSION_TRACKING;
+ ctrl->ldctl_iscritical = 0;
+
+ rs->sr_err = LDAP_SUCCESS;
+
+done:;
+ return rs->sr_err;
+}
+
+int
+slap_ctrl_session_tracking_request_add( Operation *op, SlapReply *rs, LDAPControl *ctrl )
+{
+ static struct berval bv_unknown = BER_BVC( SLAP_STRING_UNKNOWN );
+ struct berval ip = BER_BVNULL,
+ name = BER_BVNULL,
+ id = BER_BVNULL;
+
+ if ( !BER_BVISNULL( &op->o_conn->c_peer_name ) &&
+ memcmp( op->o_conn->c_peer_name.bv_val, "IP=", STRLENOF( "IP=" ) ) == 0 )
+ {
+ char *ptr;
+
+ ip.bv_val = op->o_conn->c_peer_name.bv_val + STRLENOF( "IP=" );
+ ip.bv_len = op->o_conn->c_peer_name.bv_len - STRLENOF( "IP=" );
+
+ ptr = ber_bvchr( &ip, ':' );
+ if ( ptr ) {
+ ip.bv_len = ptr - ip.bv_val;
+ }
+ }
+
+ if ( !BER_BVISNULL( &op->o_conn->c_peer_domain ) &&
+ !bvmatch( &op->o_conn->c_peer_domain, &bv_unknown ) )
+ {
+ name = op->o_conn->c_peer_domain;
+ }
+
+ if ( !BER_BVISNULL( &op->o_dn ) && !BER_BVISEMPTY( &op->o_dn ) ) {
+ id = op->o_dn;
+ }
+
+ return slap_ctrl_session_tracking_add( op, rs, &ip, &name, &id, ctrl );
+}
+#endif
+
+#ifdef SLAP_CONTROL_X_WHATFAILED
+static int parseWhatFailed(
+ Operation *op,
+ SlapReply *rs,
+ LDAPControl *ctrl )
+{
+ if ( op->o_whatFailed != SLAP_CONTROL_NONE ) {
+ rs->sr_text = "\"WHat Failed?\" control specified multiple times";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ if ( !BER_BVISNULL( &ctrl->ldctl_value )) {
+ rs->sr_text = "\"What Failed?\" control value not absent";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ op->o_whatFailed = ctrl->ldctl_iscritical
+ ? SLAP_CONTROL_CRITICAL
+ : SLAP_CONTROL_NONCRITICAL;
+
+ return LDAP_SUCCESS;
+}
+
+int
+slap_ctrl_whatFailed_add(
+ Operation *op,
+ SlapReply *rs,
+ char **oids )
+{
+ BerElementBuffer berbuf;
+ BerElement *ber = (BerElement *) &berbuf;
+ LDAPControl **ctrls = NULL;
+ struct berval ctrlval;
+ int i, rc = LDAP_SUCCESS;
+
+ ber_init2( ber, NULL, LBER_USE_DER );
+ ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
+ ber_printf( ber, "[" /*]*/ );
+ for ( i = 0; oids[ i ] != NULL; i++ ) {
+ ber_printf( ber, "s", oids[ i ] );
+ }
+ ber_printf( ber, /*[*/ "]" );
+
+ if ( ber_flatten2( ber, &ctrlval, 0 ) == -1 ) {
+ rc = LDAP_OTHER;
+ goto done;
+ }
+
+ i = 0;
+ if ( rs->sr_ctrls != NULL ) {
+ for ( ; rs->sr_ctrls[ i ] != NULL; i++ ) {
+ if ( strcmp( rs->sr_ctrls[ i ]->ldctl_oid, LDAP_CONTROL_X_WHATFAILED ) != 0 ) {
+ /* TODO: add */
+ assert( 0 );
+ }
+ }
+ }
+
+ ctrls = op->o_tmprealloc( rs->sr_ctrls,
+ sizeof(LDAPControl *)*( i + 2 )
+ + sizeof(LDAPControl)
+ + ctrlval.bv_len + 1,
+ op->o_tmpmemctx );
+ if ( ctrls == NULL ) {
+ rc = LDAP_OTHER;
+ goto done;
+ }
+ ctrls[ i + 1 ] = NULL;
+ ctrls[ i ] = (LDAPControl *)&ctrls[ i + 2 ];
+ ctrls[ i ]->ldctl_oid = LDAP_CONTROL_X_WHATFAILED;
+ ctrls[ i ]->ldctl_iscritical = 0;
+ ctrls[ i ]->ldctl_value.bv_val = (char *)&ctrls[ i ][ 1 ];
+ AC_MEMCPY( ctrls[ i ]->ldctl_value.bv_val, ctrlval.bv_val, ctrlval.bv_len + 1 );
+ ctrls[ i ]->ldctl_value.bv_len = ctrlval.bv_len;
+
+ ber_free_buf( ber );
+
+ rs->sr_ctrls = ctrls;
+
+done:;
+ return rc;
+}