]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/slap.h
use macros for fake connid
[openldap] / servers / slapd / slap.h
index 15b102ddca4cf232c33786577aec4dba8d8d9db4..bc31eea45ed6459b51dd93c0b2c26130dd30c0a8 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 1998-2007 The OpenLDAP Foundation.
+ * Copyright 1998-2009 The OpenLDAP Foundation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 
 LDAP_BEGIN_DECL
 
-#define SLAP_LIGHTWEIGHT_DISPATCHER /* experimental slapd architecture */
-
 #ifdef LDAP_DEVEL
 #define LDAP_COLLECTIVE_ATTRIBUTES
 #define LDAP_COMP_MATCH
 #define LDAP_SYNC_TIMESTAMP
-#define SLAP_SORTEDRESULTS
+#define SLAP_CONTROL_X_SESSION_TRACKING
+#define SLAP_CONTROL_X_WHATFAILED
+#define SLAP_CONFIG_DELETE
 #endif
 
 #define LDAP_DYNAMIC_OBJECTS
@@ -100,6 +100,13 @@ LDAP_BEGIN_DECL
 #define SERVICE_NAME  OPENLDAP_PACKAGE "-slapd"
 #define SLAPD_ANONYMOUS ""
 
+#ifdef HAVE_TCPD
+# include <tcpd.h>
+# define SLAP_STRING_UNKNOWN   STRING_UNKNOWN
+#else /* ! TCP Wrappers */
+# define SLAP_STRING_UNKNOWN   "unknown"
+#endif /* ! TCP Wrappers */
+
 /* LDAPMod.mod_op value ===> Must be kept in sync with ldap.h!
  * This is a value used internally by the backends. It is needed to allow
  * adding values that already exist without getting an error as required by
@@ -246,6 +253,9 @@ typedef struct slap_ssf_set {
 #define SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT              4
 #define SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT             2
 
+/* default for ordered integer index keys */
+#define SLAP_INDEX_INTLEN_DEFAULT      4
+
 #define SLAP_INDEX_FLAGS         0xF000UL
 #define SLAP_INDEX_NOSUBTYPES    0x1000UL /* don't use index w/ subtypes */
 #define SLAP_INDEX_NOTAGS        0x2000UL /* don't use index w/ tags */
@@ -290,6 +300,8 @@ enum {
        SLAP_SCHERR_SYN_NOT_FOUND,
        SLAP_SCHERR_SYN_DUP,
        SLAP_SCHERR_SYN_SUP_NOT_FOUND,
+       SLAP_SCHERR_SYN_SUBST_NOT_SPECIFIED,
+       SLAP_SCHERR_SYN_SUBST_NOT_FOUND,
        SLAP_SCHERR_NO_NAME,
        SLAP_SCHERR_NOT_SUPPORTED,
        SLAP_SCHERR_BAD_DESCR,
@@ -405,6 +417,7 @@ struct Syntax {
 #else
 #define SLAP_SYNTAX_HIDE       0x8000U /* hide (do not publish) */
 #endif
+#define        SLAP_SYNTAX_HARDCODE    0x10000U        /* This is hardcoded schema */
 
        Syntax                          **ssyn_sups;
 
@@ -421,7 +434,7 @@ struct Syntax {
        struct ComponentDesc* ssync_comp_syntax;
 #endif
 
-       LDAP_SLIST_ENTRY(Syntax)        ssyn_next;
+       LDAP_STAILQ_ENTRY(Syntax)       ssyn_next;
 };
 
 #define slap_syntax_is_flag(s,flag) ((int)((s)->ssyn_flags & (flag)) ? 1 : 0)
@@ -548,7 +561,8 @@ struct MatchingRule {
  */
 #define SLAP_MR_VALUE_OF_ASSERTION_SYNTAX      0x0001U
 #define SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX      0x0002U
-#define SLAP_MR_VALUE_OF_SYNTAX                        0x0003U
+#define SLAP_MR_VALUE_OF_SYNTAX                        (SLAP_MR_VALUE_OF_ASSERTION_SYNTAX|SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX)
+#define SLAP_MR_DENORMALIZE                    (SLAP_MR_MUTATION_NORMALIZER)
 
 #define SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX( usage ) \
        ((usage) & SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX )
@@ -560,6 +574,8 @@ struct MatchingRule {
 #else
 #define SLAP_MR_IS_VALUE_OF_SYNTAX( usage )    (1)
 #endif
+#define SLAP_MR_IS_DENORMALIZE( usage ) \
+       ((usage) & SLAP_MR_DENORMALIZE )
 
 /* either or both the asserted value or attribute value
  * may be provided in normalized form
@@ -668,7 +684,8 @@ struct AttributeType {
        Syntax                          *sat_syntax;
 
        AttributeTypeSchemaCheckFN      *sat_check;
-       char                            *sat_oidmacro;
+       char                            *sat_oidmacro;  /* attribute OID */
+       char                            *sat_soidmacro; /* syntax OID */
 
 #define SLAP_AT_NONE                   0x0000U
 #define SLAP_AT_ABSTRACT               0x0100U /* cannot be instantiated */
@@ -682,10 +699,19 @@ struct AttributeType {
 
 #define SLAP_AT_MANAGEABLE             0x0800U /* no-user-mod can be by-passed */
 
+/* Note: ORDERED values have an ordering specifically set by the
+ * user, denoted by the {x} ordering prefix on the values.
+ *
+ * SORTED values are simply sorted by memcmp. SORTED values can
+ * be efficiently located by binary search. ORDERED values have no
+ * such advantage. An attribute cannot have both properties.
+ */
 #define        SLAP_AT_ORDERED_VAL             0x0001U /* values are ordered */
 #define        SLAP_AT_ORDERED_SIB             0x0002U /* siblings are ordered */
 #define        SLAP_AT_ORDERED                 0x0003U /* value has order index */
 
+#define        SLAP_AT_SORTED_VAL              0x0010U /* values should be sorted */
+
 #define        SLAP_AT_HARDCODE                0x10000U        /* hardcoded schema */
 #define        SLAP_AT_DELETED                 0x20000U
 
@@ -816,10 +842,13 @@ struct AttributeDescription {
 #define SLAP_AD_PROXIED                0x01U
 #define        SLAP_AD_NOINSERT        0x02U
 
+#define        SLAP_AN_OCEXCLUDE       0x01
+#define        SLAP_AN_OCINITED        0x02
+
 struct AttributeName {
        struct berval           an_name;
        AttributeDescription    *an_desc;
-       int                     an_oc_exclude;
+       int                     an_flags;
        ObjectClass             *an_oc;
 };
 
@@ -946,6 +975,8 @@ struct slap_internal_schema {
        MatchingRule    *si_mr_integerMatch;
        MatchingRule    *si_mr_integerFirstComponentMatch;
        MatchingRule    *si_mr_objectIdentifierFirstComponentMatch;
+       MatchingRule    *si_mr_caseIgnoreMatch;
+       MatchingRule    *si_mr_caseIgnoreListMatch;
 
        /* Syntaxes */
        Syntax          *si_syn_directoryString;
@@ -971,6 +1002,11 @@ struct AttributeAssertion {
        ComponentFilter         *aa_cf;         /* for attribute aliasing */
 #endif
 };
+#ifdef LDAP_COMP_MATCH
+#define ATTRIBUTEASSERTION_INIT { NULL, BER_BVNULL, NULL }
+#else
+#define ATTRIBUTEASSERTION_INIT { NULL, BER_BVNULL }
+#endif
 
 struct SubstringsAssertion {
        AttributeDescription    *sa_desc;
@@ -980,11 +1016,11 @@ struct SubstringsAssertion {
 };
 
 struct MatchingRuleAssertion {
+       AttributeDescription    *ma_desc;       /* optional */
+       struct berval           ma_value;       /* required */
        MatchingRule            *ma_rule;       /* optional */
        struct berval           ma_rule_text;   /* optional */
-       AttributeDescription    *ma_desc;       /* optional */
        int                     ma_dnattrs;     /* boolean */
-       struct berval           ma_value;       /* required */
 #ifdef LDAP_COMP_MATCH
        ComponentFilter         *ma_cf; /* component filter */
 #endif
@@ -1096,20 +1132,28 @@ struct ValuesReturnFilter {
 
 /*
  * represents an attribute (description + values)
+ * desc, vals, nvals, numvals fields must align with Modification
  */
 struct Attribute {
        AttributeDescription    *a_desc;
        BerVarray               a_vals;         /* preserved values */
        BerVarray               a_nvals;        /* normalized values */
-#ifdef LDAP_COMP_MATCH
-       ComponentData           *a_comp_data;   /* component values */
-#endif
-       Attribute               *a_next;
+       unsigned                a_numvals;      /* number of vals */
        unsigned                a_flags;
 #define SLAP_ATTR_IXADD                        0x1U
 #define SLAP_ATTR_IXDEL                        0x2U
 #define SLAP_ATTR_DONT_FREE_DATA       0x4U
 #define SLAP_ATTR_DONT_FREE_VALS       0x8U
+#define        SLAP_ATTR_SORTED_VALS           0x10U   /* values are sorted */
+
+/* These flags persist across an attr_dup() */
+#define        SLAP_ATTR_PERSISTENT_FLAGS \
+       SLAP_ATTR_SORTED_VALS
+
+       Attribute               *a_next;
+#ifdef LDAP_COMP_MATCH
+       ComponentData           *a_comp_data;   /* component values */
+#endif
 };
 
 
@@ -1156,8 +1200,13 @@ struct Entry {
 
 /*
  * A list of LDAPMods
+ * desc, values, nvalues, numvals must align with Attribute
  */
 struct Modification {
+       AttributeDescription *sm_desc;
+       BerVarray sm_values;
+       BerVarray sm_nvalues;
+       unsigned sm_numvals;
        short sm_op;
        short sm_flags;
 /* Set for internal mods, will bypass ACL checks. Only needed when
@@ -1165,11 +1214,7 @@ struct Modification {
  */
 #define        SLAP_MOD_INTERNAL       0x01
 #define        SLAP_MOD_MANAGING       0x02
-
-       AttributeDescription *sm_desc;
        struct berval sm_type;
-       BerVarray sm_values;
-       BerVarray sm_nvalues;
 };
 
 struct Modifications {
@@ -1180,17 +1225,10 @@ struct Modifications {
 #define        sml_type        sml_mod.sm_type
 #define sml_values     sml_mod.sm_values
 #define sml_nvalues    sml_mod.sm_nvalues
+#define sml_numvals    sml_mod.sm_numvals
        Modifications   *sml_next;
 };
 
-struct LDAPModList {
-       LDAPMod         ml_mod;
-       LDAPModList     *ml_next;
-#define ml_op          ml_mod.mod_op
-#define ml_type                ml_mod.mod_type
-#define ml_values      ml_mod.mod_values
-};
-
 /*
  * represents an access control list
  */
@@ -1343,8 +1381,8 @@ typedef struct Access {
 #define ACL_PRIV_SET(m,p)              do { (m) |=  (p); } while(0)
 #define ACL_PRIV_CLR(m,p)              do { (m) &= ~(p); } while(0)
 
-#define ACL_INIT(m)                    ACL_PRIV_ASSIGN(m, ACL_PRIV_NONE)
-#define ACL_INVALIDATE(m)              ACL_PRIV_ASSIGN(m, ACL_PRIV_INVALID)
+#define ACL_INIT(m)                    ACL_PRIV_ASSIGN((m), ACL_PRIV_NONE)
+#define ACL_INVALIDATE(m)              ACL_PRIV_ASSIGN((m), ACL_PRIV_INVALID)
 
 #define ACL_GRANT(m,a)                 ACL_PRIV_ISSET((m),ACL_ACCESS2PRIV(a))
 
@@ -1489,26 +1527,34 @@ typedef struct AccessControl {
        struct AccessControl    *acl_next;
 } AccessControl;
 
-typedef enum {
-       ACL_STATE_NOT_RECORDED                  = 0x0,
-       ACL_STATE_RECORDED_VD                   = 0x1,
-       ACL_STATE_RECORDED_NV                   = 0x2,
-       ACL_STATE_RECORDED                      = ( ACL_STATE_RECORDED_VD | ACL_STATE_RECORDED_NV )
-} slap_acl_state_t;
-
 typedef struct AccessControlState {
        /* Access state */
-       AccessControl *as_vi_acl;
-       AccessControl *as_vd_acl;
-       AttributeDescription *as_vd_ad;
 
+       /* The stored state is valid when requesting as_access access
+        * to the as_desc attributes.    */
+       AttributeDescription *as_desc;
+       slap_access_t   as_access;
 
-       slap_acl_state_t as_recorded;
+       /* Value dependent acl where processing can restart */
+       AccessControl  *as_vd_acl;
        int as_vd_acl_count;
+       slap_mask_t             as_vd_mask;
+
+       /* The cached result after evaluating a value independent attr.
+        * Only valid when != -1 and as_vd_acl == NULL */
        int as_result;
+
+       /* True if started to process frontend ACLs */
+       int as_fe_done;
 } AccessControlState;
-#define ACL_STATE_INIT { NULL, NULL, NULL, \
-       ACL_STATE_NOT_RECORDED, 0, 0 }
+#define ACL_STATE_INIT { NULL, ACL_NONE, NULL, 0, ACL_PRIV_NONE, -1, 0 }
+
+typedef struct AclRegexMatches {        
+       int dn_count;
+        regmatch_t dn_data[MAXREMATCHES];
+       int val_count;
+        regmatch_t val_data[MAXREMATCHES];
+} AclRegexMatches;
 
 /*
  * Backend-info
@@ -1563,6 +1609,7 @@ typedef struct slap_bindconf {
        char *sb_tls_cacertdir;
        char *sb_tls_reqcert;
        char *sb_tls_cipher_suite;
+       char *sb_tls_protocol_min;
 #ifdef HAVE_OPENSSL_CRL
        char *sb_tls_crlcheck;
 #endif
@@ -1606,6 +1653,7 @@ struct slap_limits_set {
 
 struct slap_limits {
        unsigned                lm_flags;       /* type of pattern */
+       /* Values must match lmpats[] in limits.c */
 #define SLAP_LIMITS_UNDEFINED          0x0000U
 #define SLAP_LIMITS_EXACT              0x0001U
 #define SLAP_LIMITS_BASE               SLAP_LIMITS_EXACT
@@ -1618,8 +1666,10 @@ struct slap_limits {
 #define SLAP_LIMITS_ANY                        0x0008U
 #define SLAP_LIMITS_MASK               0x000FU
 
-#define SLAP_LIMITS_TYPE_DN            0x0000U
+#define SLAP_LIMITS_TYPE_SELF          0x0000U
+#define SLAP_LIMITS_TYPE_DN            SLAP_LIMITS_TYPE_SELF
 #define SLAP_LIMITS_TYPE_GROUP         0x0010U
+#define SLAP_LIMITS_TYPE_THIS          0x0020U
 #define SLAP_LIMITS_TYPE_MASK          0x00F0U
 
        regex_t                 lm_regex;       /* regex data for REGEX */
@@ -1651,12 +1701,15 @@ typedef BackendDB Backend;
 
 struct syncinfo_s;
 
-#define SLAP_SYNC_RID_SIZE     3
+/* fake conn connid constructed as SLAPD_SYNC_CONN_OFFSET - rid */
+#define SLAPD_SYNC_SYNCCONN_OFFSET (-1000)
+#define SLAPD_SYNC_IS_SYNCCONN(connid) ((connid) <= SLAPD_SYNC_SYNCCONN_OFFSET)
+#define SLAPD_SYNC_RID2SYNCCONN(rid) (SLAPD_SYNC_SYNCCONN_OFFSET - (rid))
+
+#define SLAP_SYNC_RID_MAX      999
 #define SLAP_SYNC_SID_MAX      4095    /* based on liblutil/csn.c field width */
 #define SLAP_SYNCUUID_SET_SIZE 256
 
-#define        SLAP_SYNC_UPDATE_MSGID  1
-
 struct sync_cookie {
        struct berval *ctxcsn;
        struct berval octet_str;
@@ -1679,6 +1732,7 @@ struct ConfigOCs; /* config.h */
 
 struct BackendDB {
        BackendInfo     *bd_info;       /* pointer to shared backend info */
+       BackendDB       *bd_self;       /* pointer to this struct */
 
        /* fields in this structure (and routines acting on this structure)
           should be renamed from be_ to bd_ */
@@ -1696,9 +1750,9 @@ struct BackendDB {
 #define                be_modrdn       bd_info->bi_op_modrdn
 #define                be_search       bd_info->bi_op_search
 #define                be_abandon      bd_info->bi_op_abandon
-#define                be_cancel       bd_info->bi_op_cancel
 
 #define                be_extended     bd_info->bi_extended
+#define                be_cancel       bd_info->bi_op_cancel
 
 #define                be_chk_referrals        bd_info->bi_chk_referrals
 #define                be_chk_controls         bd_info->bi_chk_controls
@@ -1727,7 +1781,6 @@ struct BackendDB {
 #define                be_entry_put bd_info->bi_tool_entry_put
 #define                be_sync bd_info->bi_tool_sync
 #define                be_dn2id_get bd_info->bi_tool_dn2id_get
-#define                be_id2entry_get bd_info->bi_tool_id2entry_get
 #define                be_entry_modify bd_info->bi_tool_entry_modify
 #endif
 
@@ -1740,6 +1793,7 @@ struct BackendDB {
 #define SLAP_DBFLAG_NOLASTMOD          0x0001U
 #define SLAP_DBFLAG_NO_SCHEMA_CHECK    0x0002U
 #define        SLAP_DBFLAG_HIDDEN              0x0004U
+#define        SLAP_DBFLAG_ONE_SUFFIX          0x0008U
 #define        SLAP_DBFLAG_GLUE_INSTANCE       0x0010U /* a glue backend */
 #define        SLAP_DBFLAG_GLUE_SUBORDINATE    0x0020U /* child of a glue hierarchy */
 #define        SLAP_DBFLAG_GLUE_LINKED         0x0040U /* child is connected to parent */
@@ -1752,11 +1806,16 @@ struct BackendDB {
 #define SLAP_DBFLAG_SINGLE_SHADOW      0x4000U /* a single-master shadow */
 #define SLAP_DBFLAG_SYNC_SHADOW                0x1000U /* a sync shadow */
 #define SLAP_DBFLAG_SLURP_SHADOW       0x2000U /* a slurp shadow */
+#define SLAP_DBFLAG_SHADOW_MASK                (SLAP_DBFLAG_SHADOW|SLAP_DBFLAG_SINGLE_SHADOW|SLAP_DBFLAG_SYNC_SHADOW|SLAP_DBFLAG_SLURP_SHADOW)
+#define SLAP_DBFLAG_CLEAN              0x10000U /* was cleanly shutdown */
+#define SLAP_DBFLAG_ACL_ADD            0x20000U /* check attr ACLs on adds */
+#define SLAP_DBFLAG_SYNC_SUBENTRY      0x40000U /* use subentry for context */
        slap_mask_t     be_flags;
 #define SLAP_DBFLAGS(be)                       ((be)->be_flags)
 #define SLAP_NOLASTMOD(be)                     (SLAP_DBFLAGS(be) & SLAP_DBFLAG_NOLASTMOD)
 #define SLAP_LASTMOD(be)                       (!SLAP_NOLASTMOD(be))
 #define SLAP_DBHIDDEN(be)                      (SLAP_DBFLAGS(be) & SLAP_DBFLAG_HIDDEN)
+#define SLAP_DB_ONE_SUFFIX(be)         (SLAP_DBFLAGS(be) & SLAP_DBFLAG_ONE_SUFFIX)
 #define SLAP_ISOVERLAY(be)                     (SLAP_DBFLAGS(be) & SLAP_DBFLAG_OVERLAY)
 #define SLAP_ISGLOBALOVERLAY(be)               (SLAP_DBFLAGS(be) & SLAP_DBFLAG_GLOBAL_OVERLAY)
 #define SLAP_DBMONITORING(be)                  (SLAP_DBFLAGS(be) & SLAP_DBFLAG_MONITORING)
@@ -1775,6 +1834,9 @@ struct BackendDB {
 #define SLAP_SLURP_SHADOW(be)                  (SLAP_DBFLAGS(be) & SLAP_DBFLAG_SLURP_SHADOW)
 #define SLAP_SINGLE_SHADOW(be)                 (SLAP_DBFLAGS(be) & SLAP_DBFLAG_SINGLE_SHADOW)
 #define SLAP_MULTIMASTER(be)                   (!SLAP_SINGLE_SHADOW(be))
+#define SLAP_DBCLEAN(be)                       (SLAP_DBFLAGS(be) & SLAP_DBFLAG_CLEAN)
+#define SLAP_DBACL_ADD(be)                     (SLAP_DBFLAGS(be) & SLAP_DBFLAG_ACL_ADD)
+#define SLAP_SYNC_SUBENTRY(be)                 (SLAP_DBFLAGS(be) & SLAP_DBFLAG_SYNC_SUBENTRY)
 
        slap_mask_t     be_restrictops;         /* restriction operations */
 #define SLAP_RESTRICT_OP_ADD           0x0001U
@@ -1822,6 +1884,9 @@ struct BackendDB {
 #define SLAP_DISALLOW_TLS_2_ANON       0x0010U /* StartTLS -> Anonymous */
 #define SLAP_DISALLOW_TLS_AUTHC                0x0020U /* TLS while authenticated */
 
+#define SLAP_DISALLOW_PROXY_AUTHZ_N_CRIT       0x0100U
+#define SLAP_DISALLOW_DONTUSECOPY_N_CRIT       0x0200U
+
 #define SLAP_DISALLOW_AUX_WO_CR                0x4000U
 
        slap_mask_t     be_requires;    /* pre-operation requirements */
@@ -1854,7 +1919,6 @@ struct BackendDB {
        BerVarray       be_update_refs; /* where to refer modifying clients to */
        struct          be_pcl  *be_pending_csn_list;
        ldap_pvt_thread_mutex_t                                 be_pcl_mutex;
-       ldap_pvt_thread_mutex_t                                 *be_pcl_mutexp;
        struct syncinfo_s                                               *be_syncinfo; /* For syncrepl */
 
        void    *be_pb;         /* Netscape plugin */
@@ -1874,8 +1938,8 @@ typedef int (BI_config) LDAP_P((BackendInfo *bi,
        const char *fname, int lineno,
        int argc, char **argv));
 
-struct config_args_s; /* config.h */
-typedef int (BI_db_func) LDAP_P((Backend *bd, struct config_args_s *ca));
+typedef struct config_reply_s ConfigReply; /* config.h */
+typedef int (BI_db_func) LDAP_P((Backend *bd, ConfigReply *cr));
 typedef BI_db_func BI_db_init;
 typedef BI_db_func BI_db_open;
 typedef BI_db_func BI_db_close;
@@ -1889,7 +1953,7 @@ typedef struct req_bind_s {
        struct berval rb_cred;
        struct berval rb_edn;
        slap_ssf_t rb_ssf;
-       struct berval rb_tmp_mech;      /* FIXME: temporary */
+       struct berval rb_mech;
 } req_bind_s;
 
 typedef struct req_search_s {
@@ -1909,23 +1973,27 @@ typedef struct req_compare_s {
        AttributeAssertion *rs_ava;
 } req_compare_s;
 
-typedef struct req_modify_s {
+typedef struct req_modifications_s {
        Modifications *rs_modlist;
-       int rs_increment;               /* FIXME: temporary */
        char rs_no_opattrs;             /* don't att modify operational attrs */
+} req_modifications_s;
+
+typedef struct req_modify_s {
+       req_modifications_s rs_mods;    /* NOTE: must be first in req_modify_s & req_modrdn_s */
+       int rs_increment;
 } req_modify_s;
 
 typedef struct req_modrdn_s {
-       Modifications *rs_modlist;
+       req_modifications_s rs_mods;    /* NOTE: must be first in req_modify_s & req_modrdn_s */
+       int rs_deleteoldrdn;
        struct berval rs_newrdn;
        struct berval rs_nnewrdn;
        struct berval *rs_newSup;
        struct berval *rs_nnewSup;
-       int rs_deleteoldrdn;
 } req_modrdn_s;
 
 typedef struct req_add_s {
-       Modifications *rs_modlist;      /* FIXME: temporary */
+       Modifications *rs_modlist;
        Entry *rs_e;
 } req_add_s;
 
@@ -2003,9 +2071,9 @@ struct SlapReply {
        BerVarray sr_ref;
        LDAPControl **sr_ctrls;
        union sr_u {
+               rep_search_s sru_search;
                rep_sasl_s sru_sasl;
                rep_extended_s sru_extended;
-               rep_search_s sru_search;
        } sr_un;
        slap_mask_t sr_flags;
 #define REP_ENTRY_MODIFIABLE   0x0001U
@@ -2019,6 +2087,9 @@ struct SlapReply {
 #define REP_REF_MUSTBEFREED    0x0020U
 #define REP_REF_MASK           (REP_REF_MUSTBEFREED)
 
+#define REP_CTRLS_MUSTBEFREED  0x0040U
+#define REP_CTRLS_MASK         (REP_CTRLS_MUSTBEFREED)
+
 #define        REP_NO_ENTRYDN          0x1000U
 #define        REP_NO_SUBSCHEMA        0x2000U
 #define        REP_NO_OPERATIONALS     (REP_NO_ENTRYDN|REP_NO_SUBSCHEMA)
@@ -2045,8 +2116,8 @@ typedef BI_op_func BI_op_modrdn;
 typedef BI_op_func BI_op_add;
 typedef BI_op_func BI_op_delete;
 typedef BI_op_func BI_op_abandon;
-typedef BI_op_func BI_op_cancel;
 typedef BI_op_func BI_op_extended;
+typedef BI_op_func BI_op_cancel;
 typedef BI_op_func BI_chk_referrals;
 typedef BI_op_func BI_chk_controls;
 typedef int (BI_entry_release_rw)
@@ -2080,7 +2151,6 @@ typedef ID (BI_tool_entry_put) LDAP_P(( BackendDB *be, Entry *e,
 typedef int (BI_tool_entry_reindex) LDAP_P(( BackendDB *be, ID id, AttributeDescription **adv ));
 typedef int (BI_tool_sync) LDAP_P(( BackendDB *be ));
 typedef ID (BI_tool_dn2id_get) LDAP_P(( BackendDB *be, struct berval *dn ));
-typedef int (BI_tool_id2entry_get) LDAP_P(( BackendDB *be, ID id, Entry **e ));
 typedef ID (BI_tool_entry_modify) LDAP_P(( BackendDB *be, Entry *e, 
        struct berval *text ));
 
@@ -2150,10 +2220,10 @@ struct BackendInfo {
        BI_op_add       *bi_op_add;
        BI_op_delete    *bi_op_delete;
        BI_op_abandon   *bi_op_abandon;
-       BI_op_cancel    *bi_op_cancel;
 
        /* Extended Operations Helper */
        BI_op_extended  *bi_extended;
+       BI_op_cancel    *bi_op_cancel;
 
        /* Auxilary Functions */
        BI_operational          *bi_operational;
@@ -2180,7 +2250,6 @@ struct BackendInfo {
        BI_tool_entry_reindex   *bi_tool_entry_reindex;
        BI_tool_sync            *bi_tool_sync;
        BI_tool_dn2id_get       *bi_tool_dn2id_get;
-       BI_tool_id2entry_get    *bi_tool_id2entry_get;
        BI_tool_entry_modify    *bi_tool_entry_modify;
 
 #define SLAP_INDEX_ADD_OP              0x0001
@@ -2270,8 +2339,8 @@ typedef enum slap_operation_e {
        op_add,
        op_delete,
        op_abandon,
-       op_cancel,
        op_extended,
+       op_cancel,
        op_aux_operational,
        op_aux_chk_referrals,
        op_aux_chk_controls,
@@ -2293,7 +2362,6 @@ typedef struct slap_overinfo {
 } slap_overinfo;
 
 /* Should successive callbacks in a chain be processed? */
-#define        SLAP_CB_FREEME          0x04000
 #define        SLAP_CB_BYPASS          0x08800
 #define        SLAP_CB_CONTINUE        0x08000
 
@@ -2304,12 +2372,14 @@ typedef unsigned long PagedResultsCookie;
 typedef struct PagedResultsState {
        Backend *ps_be;
        ber_int_t ps_size;
-       PagedResultsCookie ps_cookie;
        int ps_count;
+       PagedResultsCookie ps_cookie;
+       struct berval ps_cookieval;
 } PagedResultsState;
 
 struct slap_csn_entry {
        struct berval ce_csn;
+       int ce_sid;
        unsigned long ce_opid;
        unsigned long ce_connid;
 #define SLAP_CSN_PENDING       1
@@ -2346,17 +2416,58 @@ struct slap_control_ids {
        int sc_proxyAuthz;
        int sc_relax;
        int sc_searchOptions;
-#ifdef SLAP_SORTEDRESULTS
+#ifdef SLAP_CONTROL_X_SORTEDRESULTS
        int sc_sortedResults;
 #endif
        int sc_subentries;
+#ifdef SLAP_CONTROL_X_TREE_DELETE
        int sc_treeDelete;
+#endif
 #ifdef LDAP_X_TXN
        int sc_txnSpec;
+#endif
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+       int sc_sessionTracking;
 #endif
        int sc_valuesReturnFilter;
+#ifdef SLAP_CONTROL_X_WHATFAILED
+       int sc_whatFailed;
+#endif
 };
 
+/*
+ * Operation indices
+ */
+typedef enum {
+       SLAP_OP_BIND = 0,
+       SLAP_OP_UNBIND,
+       SLAP_OP_SEARCH,
+       SLAP_OP_COMPARE,
+       SLAP_OP_MODIFY,
+       SLAP_OP_MODRDN,
+       SLAP_OP_ADD,
+       SLAP_OP_DELETE,
+       SLAP_OP_ABANDON,
+       SLAP_OP_EXTENDED,
+       SLAP_OP_LAST
+} slap_op_t;
+
+typedef struct slap_counters_t {
+       struct slap_counters_t  *sc_next;
+       ldap_pvt_thread_mutex_t sc_mutex;
+       ldap_pvt_mp_t           sc_bytes;
+       ldap_pvt_mp_t           sc_pdu;
+       ldap_pvt_mp_t           sc_entries;
+       ldap_pvt_mp_t           sc_refs;
+
+       ldap_pvt_mp_t           sc_ops_completed;
+       ldap_pvt_mp_t           sc_ops_initiated;
+#ifdef SLAPD_MONITOR
+       ldap_pvt_mp_t           sc_ops_completed_[SLAP_OP_LAST];
+       ldap_pvt_mp_t           sc_ops_initiated_[SLAP_OP_LAST];
+#endif /* SLAPD_MONITOR */
+} slap_counters_t;
+
 /*
  * represents an operation pending from an ldap client
  */
@@ -2374,7 +2485,9 @@ typedef struct Opheader {
        void    *oh_tmpmemctx;          /* slab malloc context */
        BerMemoryFunctions *oh_tmpmfuncs;
 
-       char            oh_log_prefix[sizeof("conn=18446744073709551615 op=18446744073709551615")];
+       slap_counters_t *oh_counters;
+
+       char            oh_log_prefix[ /* sizeof("conn= op=") + 2*LDAP_PVT_INTTYPE_CHARS(unsigned long) */ SLAP_TEXT_BUFLEN ];
 
 #ifdef LDAP_SLAPI
        void    *oh_extensions;         /* NS-SLAPI plugin */
@@ -2394,6 +2507,20 @@ typedef union OpRequest {
        req_pwdexop_s oq_pwdexop;
 } OpRequest;
 
+/* This is only a header. Actual users should define their own
+ * structs with the oe_next / oe_key fields at the top and
+ * whatever else they need following.
+ */
+typedef struct OpExtra {
+       LDAP_SLIST_ENTRY(OpExtra) oe_next;
+       void *oe_key;
+} OpExtra;
+
+typedef struct OpExtraDB {
+       OpExtra oe;
+       BackendDB *oe_db;
+} OpExtraDB;
+
 struct Operation {
        Opheader *o_hdr;
 
@@ -2406,6 +2533,7 @@ struct Operation {
 #define o_threadctx o_hdr->oh_threadctx
 #define o_tmpmemctx o_hdr->oh_tmpmemctx
 #define o_tmpmfuncs o_hdr->oh_tmpmfuncs
+#define o_counters o_hdr->oh_counters
 
 #define        o_tmpalloc      o_tmpmfuncs->bmf_malloc
 #define o_tmpcalloc    o_tmpmfuncs->bmf_calloc
@@ -2441,7 +2569,7 @@ struct Operation {
 #define orb_cred oq_bind.rb_cred
 #define orb_edn oq_bind.rb_edn
 #define orb_ssf oq_bind.rb_ssf
-#define orb_tmp_mech oq_bind.rb_tmp_mech
+#define orb_mech oq_bind.rb_mech
 
 #define ors_scope oq_search.rs_scope
 #define ors_deref oq_search.rs_deref
@@ -2453,20 +2581,24 @@ struct Operation {
 #define ors_filter oq_search.rs_filter
 #define ors_filterstr oq_search.rs_filterstr
 
+#define orr_modlist oq_modrdn.rs_mods.rs_modlist
+#define orr_no_opattrs oq_modrdn.rs_mods.rs_no_opattrs
+#define orr_deleteoldrdn oq_modrdn.rs_deleteoldrdn
 #define orr_newrdn oq_modrdn.rs_newrdn
 #define orr_nnewrdn oq_modrdn.rs_nnewrdn
 #define orr_newSup oq_modrdn.rs_newSup
 #define orr_nnewSup oq_modrdn.rs_nnewSup
-#define orr_deleteoldrdn oq_modrdn.rs_deleteoldrdn
-#define orr_modlist oq_modrdn.rs_modlist
 
 #define orc_ava oq_compare.rs_ava
+
 #define ora_e oq_add.rs_e
 #define ora_modlist oq_add.rs_modlist
+
 #define orn_msgid oq_abandon.rs_msgid
-#define orm_modlist oq_modify.rs_modlist
+
+#define orm_modlist oq_modify.rs_mods.rs_modlist
+#define orm_no_opattrs oq_modify.rs_mods.rs_no_opattrs
 #define orm_increment oq_modify.rs_increment
-#define orm_no_opattrs oq_modify.rs_no_opattrs
 
 #define ore_reqoid oq_extended.rs_reqoid
 #define ore_flags oq_extended.rs_flags
@@ -2481,6 +2613,7 @@ struct Operation {
        GroupAssertion *o_groups;
        char o_do_not_cache;    /* don't cache groups from this op */
        char o_is_auth_check;   /* authorization in progress */
+       char o_dont_replicate;
        slap_access_t o_acl_priv;
 
        char o_nocaching;
@@ -2541,8 +2674,10 @@ struct Operation {
 #define o_domain_scope o_ctrlflag[slap_cids.sc_domainScope]
 #define get_domainScope(op)                            ((int)(op)->o_domain_scope)
 
+#ifdef SLAP_CONTROL_X_TREE_DELETE
 #define        o_tree_delete   o_ctrlflag[slap_cids.sc_treeDelete]
 #define get_treeDelete(op)                             ((int)(op)->o_tree_delete)
+#endif
 
 #define o_preread      o_ctrlflag[slap_cids.sc_preRead]
 #define o_postread     o_ctrlflag[slap_cids.sc_postRead]
@@ -2554,7 +2689,7 @@ struct Operation {
 #define o_pagedresults_state   o_controls[slap_cids.sc_pagedResults]
 #define get_pagedresults(op)                   ((int)(op)->o_pagedresults)
 
-#ifdef SLAP_SORTEDRESULTS
+#ifdef SLAP_CONTROL_X_SORTEDRESULTS
 #define o_sortedresults                o_ctrlflag[slap_cids.sc_sortedResults]
 #endif
 
@@ -2562,6 +2697,17 @@ struct Operation {
 #define o_txnSpec              o_ctrlflag[slap_cids.sc_txnSpec]
 #endif
 
+#ifdef SLAP_CONTROL_X_SESSION_TRACKING
+#define o_session_tracking     o_ctrlflag[slap_cids.sc_sessionTracking]
+#define o_tracked_sessions     o_controls[slap_cids.sc_sessionTracking]
+#define get_sessionTracking(op)                        ((int)(op)->o_session_tracking)
+#endif
+
+#ifdef SLAP_CONTROL_X_WHATFAILED
+#define o_whatFailed o_ctrlflag[slap_cids.sc_whatFailed]
+#define get_whatFailed(op)                             _SCM((op)->o_whatFailed)
+#endif
+
 #define o_sync                 o_ctrlflag[slap_cids.sc_LDAPsync]
 
        AuthorizationInformation o_authz;
@@ -2572,7 +2718,9 @@ struct Operation {
        LDAPControl     **o_ctrls;       /* controls */
        struct berval o_csn;
 
+       /* DEPRECATE o_private - use o_extra instead */
        void    *o_private;     /* anything the backend needs */
+       LDAP_SLIST_HEAD(o_e, OpExtra) o_extra;  /* anything the backend needs */
 
        LDAP_STAILQ_ENTRY(Operation)    o_next; /* next operation in list */
 };
@@ -2585,7 +2733,7 @@ typedef struct OperationBuffer {
 
 #define send_ldap_error( op, rs, err, text ) do { \
                (rs)->sr_err = err; (rs)->sr_text = text; \
-               (op->o_conn->c_send_ldap_result)( op, rs ); \
+               ((op)->o_conn->c_send_ldap_result)( op, rs ); \
        } while (0)
 #define send_ldap_discon( op, rs, err, text ) do { \
                (rs)->sr_err = err; (rs)->sr_text = text; \
@@ -2614,15 +2762,33 @@ typedef void (SEND_LDAP_INTERMEDIATE)(
 #define send_ldap_intermediate( op, rs ) \
        ((op)->o_conn->c_send_ldap_intermediate)( op, rs )
 
-typedef struct slap_listener Listener;
+typedef struct Listener Listener;
 
 /*
  * represents a connection from an ldap client
  */
+/* structure state (protected by connections_mutex) */
+enum sc_struct_state {
+       SLAP_C_UNINITIALIZED = 0,       /* MUST BE ZERO (0) */
+       SLAP_C_UNUSED,
+       SLAP_C_USED,
+       SLAP_C_PENDING
+};
+
+/* connection state (protected by c_mutex ) */
+enum sc_conn_state {
+       SLAP_C_INVALID = 0,             /* MUST BE ZERO (0) */
+       SLAP_C_INACTIVE,                /* zero threads */
+       SLAP_C_CLOSING,                 /* closing */
+       SLAP_C_ACTIVE,                  /* one or more threads */
+       SLAP_C_BINDING,                 /* binding */
+       SLAP_C_CLIENT                   /* outbound client conn */
+};
 struct Connection {
-       int                     c_struct_state; /* structure management state */
-       int                     c_conn_state;   /* connection state */
+       enum sc_struct_state    c_struct_state; /* structure management state */
+       enum sc_conn_state      c_conn_state;   /* connection state */
        int                     c_conn_idx;             /* slot in connections array */
+       ber_socket_t    c_sd;
        const char      *c_close_reason; /* why connection is closing */
 
        ldap_pvt_thread_mutex_t c_mutex; /* protect the connection */
@@ -2640,7 +2806,6 @@ struct Connection {
 #define c_sock_name c_listener->sl_name        /* sock name (trans=addr:port) */
 
        /* only can be changed by binding thread */
-       int             c_sasl_bind_in_progress;        /* multi-op bind in progress */
        struct berval   c_sasl_bind_mech;                       /* mech in progress */
        struct berval   c_sasl_dn;      /* temporary storage */
        struct berval   c_sasl_authz_dn;        /* SASL proxy authz */
@@ -2663,11 +2828,18 @@ struct Connection {
        LDAP_STAILQ_HEAD(c_o, Operation) c_ops; /* list of operations being processed */
        LDAP_STAILQ_HEAD(c_po, Operation) c_pending_ops;        /* list of pending operations */
 
-       ldap_pvt_thread_mutex_t c_write_mutex;  /* only one pdu written at a time */
-       ldap_pvt_thread_cond_t  c_write_cv;             /* used to wait for sd write-ready*/
+       ldap_pvt_thread_mutex_t c_write1_mutex; /* only one pdu written at a time */
+       ldap_pvt_thread_cond_t  c_write1_cv;    /* only one pdu written at a time */
+       ldap_pvt_thread_mutex_t c_write2_mutex; /* used to wait for sd write-ready */
+       ldap_pvt_thread_cond_t  c_write2_cv;    /* used to wait for sd write-ready*/
 
        BerElement      *c_currentber;  /* ber we're attempting to read */
-       int             c_writewaiter;  /* true if writer is waiting */
+       int                     c_writers;              /* number of writers waiting */
+       char            c_writing;              /* someone is writing */
+
+       char            c_sasl_bind_in_progress;        /* multi-op bind in progress */
+       char            c_writewaiter;  /* true if blocked on write */
+
 
 #define        CONN_IS_TLS     1
 #define        CONN_IS_UDP     2
@@ -2675,14 +2847,14 @@ struct Connection {
 #define        CONN_IS_IPC     8
 
 #ifdef LDAP_CONNECTIONLESS
-       int     c_is_udp;               /* true if this is (C)LDAP over UDP */
+       char    c_is_udp;               /* true if this is (C)LDAP over UDP */
 #endif
 #ifdef HAVE_TLS
-       int     c_is_tls;               /* true if this LDAP over raw TLS */
-       int     c_needs_tls_accept;     /* true if SSL_accept should be called */
+       char    c_is_tls;               /* true if this LDAP over raw TLS */
+       char    c_needs_tls_accept;     /* true if SSL_accept should be called */
 #endif
-       int             c_sasl_layers;   /* true if we need to install SASL i/o handlers */
-       int     c_sasl_done;            /* SASL completed once */
+       char    c_sasl_layers;   /* true if we need to install SASL i/o handlers */
+       char    c_sasl_done;            /* SASL completed once */
        void    *c_sasl_authctx;        /* SASL authentication context */
        void    *c_sasl_sockctx;        /* SASL security layer context */
        void    *c_sasl_extra;          /* SASL session extra stuff */
@@ -2742,7 +2914,7 @@ struct Connection {
 #define Statslog( level, fmt, connid, opid, arg1, arg2, arg3 ) \
        do { \
                if ( ldap_debug & (level) ) \
-                       fprintf( stderr, (fmt), (connid), (opid), (arg1), (arg2), (arg3) );\
+                       lutil_debug( ldap_debug, (level), (fmt), (connid), (opid), (arg1), (arg2), (arg3) );\
        } while (0)
 #define StatslogTest( level ) (ldap_debug & (level))
 #endif /* !LDAP_SYSLOG */
@@ -2754,7 +2926,7 @@ struct Connection {
 /*
  * listener; need to access it from monitor backend
  */
-struct slap_listener {
+struct Listener {
        struct berval sl_url;
        struct berval sl_name;
        mode_t  sl_perms;
@@ -2765,47 +2937,19 @@ struct slap_listener {
        int     sl_is_udp;              /* UDP listener is also data port */
 #endif
        int     sl_mute;        /* Listener is temporarily disabled due to emfile */
-#ifdef SLAP_LIGHTWEIGHT_DISPATCHER
        int     sl_busy;        /* Listener is busy (accept thread activated) */
-#endif
        ber_socket_t sl_sd;
        Sockaddr sl_sa;
 #define sl_addr        sl_sa.sa_in_addr
+#ifdef LDAP_DEVEL
+#define LDAP_TCP_BUFFER
+#endif
+#ifdef LDAP_TCP_BUFFER
+       int     sl_tcp_rmem;    /* custom TCP read buffer size */
+       int     sl_tcp_wmem;    /* custom TCP write buffer size */
+#endif
 };
 
-/*
- * Operation indices
- */
-typedef enum {
-       SLAP_OP_BIND = 0,
-       SLAP_OP_UNBIND,
-       SLAP_OP_ADD,
-       SLAP_OP_DELETE,
-       SLAP_OP_MODRDN,
-       SLAP_OP_MODIFY,
-       SLAP_OP_COMPARE,
-       SLAP_OP_SEARCH,
-       SLAP_OP_ABANDON,
-       SLAP_OP_EXTENDED,
-       SLAP_OP_LAST
-} slap_op_t;
-
-typedef struct slap_counters_t {
-       ldap_pvt_thread_mutex_t sc_sent_mutex;
-       ldap_pvt_mp_t           sc_bytes;
-       ldap_pvt_mp_t           sc_pdu;
-       ldap_pvt_mp_t           sc_entries;
-       ldap_pvt_mp_t           sc_refs;
-
-       ldap_pvt_thread_mutex_t sc_ops_mutex;
-       ldap_pvt_mp_t           sc_ops_completed;
-       ldap_pvt_mp_t           sc_ops_initiated;
-#ifdef SLAPD_MONITOR
-       ldap_pvt_mp_t           sc_ops_completed_[SLAP_OP_LAST];
-       ldap_pvt_mp_t           sc_ops_initiated_[SLAP_OP_LAST];
-#endif /* SLAPD_MONITOR */
-} slap_counters_t;
-
 /*
  * Better know these all around slapd
  */