]> git.sur5r.net Git - openldap/commitdiff
allow control handlers to be replaced
authorPierangelo Masarati <ando@openldap.org>
Wed, 11 Jan 2006 19:36:18 +0000 (19:36 +0000)
committerPierangelo Masarati <ando@openldap.org>
Wed, 11 Jan 2006 19:36:18 +0000 (19:36 +0000)
servers/slapd/controls.c
servers/slapd/proto-slap.h

index 1e768bd11bb5f806c9beb8be124fa142bc28e5cf..426b9cb02c9377b6133dd2c8a6aab608a947bbb4 100644 (file)
@@ -197,21 +197,29 @@ static struct slap_control control_defs[] = {
        { NULL, 0, 0, NULL, 0, LDAP_SLIST_ENTRY_INITIALIZER(next) }
 };
 
+static struct slap_control *
+find_ctrl( const char *oid );
+
 /*
  * Register a supported control.
  *
  * This can be called by an OpenLDAP plugin or, indirectly, by a
  * SLAPI plugin calling slapi_register_supported_control().
+ *
+ * NOTE: if flags == 1 the control is replaced if already registered;
+ * otherwise registering an already registered control is not allowed.
  */
 int
-register_supported_control(const char *controloid,
+register_supported_control2(const char *controloid,
        slap_mask_t controlmask,
        char **controlexops,
        SLAP_CTRL_PARSE_FN *controlparsefn,
+       unsigned flags,
        int *controlcid)
 {
-       struct slap_control *sc;
+       struct slap_control *sc = NULL;
        int i;
+       BerVarray extendedopsbv = NULL;
 
        if ( num_known_controls >= SLAP_MAX_CIDS ) {
                Debug( LDAP_DEBUG_ANY, "Too many controls registered."
@@ -220,11 +228,23 @@ register_supported_control(const char *controloid,
                return LDAP_OTHER;
        }
 
-       if ( controloid == NULL ) return LDAP_PARAM_ERROR;
+       if ( controloid == NULL ) {
+               return LDAP_PARAM_ERROR;
+       }
 
-       /* sanity check - should never happen */
+       /* check if already registered */
        for ( i = 0; slap_known_controls[ i ]; i++ ) {
                if ( strcmp( controloid, slap_known_controls[ i ] ) == 0 ) {
+                       if ( flags == 1 ) {
+                               Debug( LDAP_DEBUG_TRACE,
+                                       "Control %s already registered; replacing.\n",
+                                       controloid, 0, 0 );
+                               /* (find and) replace existing handler */
+                               sc = find_ctrl( controloid );
+                               assert( sc != NULL );
+                               break;
+                       }
+
                        Debug( LDAP_DEBUG_ANY,
                                "Control %s already registered.\n",
                                controloid, 0, 0 );
@@ -232,41 +252,52 @@ register_supported_control(const char *controloid,
                }
        }
 
-       sc = (struct slap_control *)SLAP_MALLOC( sizeof( *sc ) );
-       if ( sc == NULL ) return LDAP_NO_MEMORY;
-
-       sc->sc_oid = ch_strdup( controloid );
-       sc->sc_mask = controlmask;
+       /* turn compatible extended operations into bervals */
        if ( controlexops != NULL ) {
                int i;
 
                for ( i = 0; controlexops[ i ]; i++ );
 
-               sc->sc_extendedopsbv = ber_memcalloc( i + 1, sizeof( struct berval ) );
-               if ( sc->sc_extendedopsbv == NULL ) {
-                       ch_free( sc );
+               extendedopsbv = ber_memcalloc( i + 1, sizeof( struct berval ) );
+               if ( extendedopsbv == NULL ) {
                        return LDAP_NO_MEMORY;
                }
 
                for ( i = 0; controlexops[ i ]; i++ ) {
-                       ber_str2bv( controlexops[ i ], 0, 1, &sc->sc_extendedopsbv[ i ] );
+                       ber_str2bv( controlexops[ i ], 0, 1, &extendedopsbv[ i ] );
+               }
+       }
+
+       if ( sc == NULL ) {
+               sc = (struct slap_control *)SLAP_MALLOC( sizeof( *sc ) );
+               if ( sc == NULL ) {
+                       return LDAP_NO_MEMORY;
                }
 
+               sc->sc_oid = ch_strdup( controloid );
+               sc->sc_cid = num_known_controls;
+
+               /* Update slap_known_controls, too. */
+               slap_known_controls[num_known_controls - 1] = sc->sc_oid;
+               slap_known_controls[num_known_controls++] = NULL;
+
+               LDAP_SLIST_NEXT( sc, sc_next ) = NULL;
+               LDAP_SLIST_INSERT_HEAD( &controls_list, sc, sc_next );
+
        } else {
-               sc->sc_extendedopsbv = NULL;
+               if ( sc->sc_extendedopsbv ) {
+                       ber_bvarray_free( sc->sc_extendedops );
+                       sc->sc_extendedops = NULL;
+               }
        }
-       sc->sc_extendedops = NULL;
-       sc->sc_parse = controlparsefn;
-
-       if ( controlcid ) *controlcid = num_known_controls;
-       sc->sc_cid = num_known_controls;
 
-       /* Update slap_known_controls, too. */
-       slap_known_controls[num_known_controls-1] = sc->sc_oid;
-       slap_known_controls[num_known_controls++] = NULL;
+       sc->sc_extendedopsbv = extendedopsbv;
+       sc->sc_mask = controlmask;
+       sc->sc_parse = controlparsefn;
+       if ( controlcid ) {
+               *controlcid = sc->sc_cid;
+       }
 
-       LDAP_SLIST_NEXT( sc, sc_next ) = NULL;
-       LDAP_SLIST_INSERT_HEAD( &controls_list, sc, sc_next );
        return LDAP_SUCCESS;
 }
 
index eae7835fa60dd63b61715f516318755efba32453..41ddfe18043e8a66534f842494704398b1f47ee4 100644 (file)
@@ -558,12 +558,15 @@ LDAP_SLAPD_F (int) get_ctrls LDAP_P((
        Operation *op,
        SlapReply *rs,
        int senderrors ));
-LDAP_SLAPD_F (int) register_supported_control LDAP_P((
+LDAP_SLAPD_F (int) register_supported_control2 LDAP_P((
        const char *controloid,
        slap_mask_t controlmask,
        char **controlexops,
        SLAP_CTRL_PARSE_FN *controlparsefn,
+       unsigned flags,
        int *controlcid ));
+#define register_supported_control(oid, mask, exops, fn, cid) \
+       register_supported_control2((oid), (mask), (exops), (fn), 0, (cid))
 LDAP_SLAPD_F (int) slap_controls_init LDAP_P ((void));
 LDAP_SLAPD_F (void) controls_destroy LDAP_P ((void));
 LDAP_SLAPD_F (int) controls_root_dse_info LDAP_P ((Entry *e));