]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/overlays/translucent.c
Plug memleak when query isn't added to cache
[openldap] / servers / slapd / overlays / translucent.c
index 85724d5f507f27f1c1b64a58da4ef55e2df0996a..3fde2b1e77154c1ba7ebcc7c3e320716d66785bd 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2004-2005 The OpenLDAP Foundation.
+ * Copyright 2004-2006 The OpenLDAP Foundation.
  * Portions Copyright 2005 Symas Corporation.
  * All rights reserved.
  *
@@ -29,6 +29,7 @@
 #include <ac/socket.h>
 
 #include "slap.h"
+#include "lutil.h"
 
 /* config block */
 
@@ -62,26 +63,20 @@ static struct berval glue[] = { BER_BVC("top"), BER_BVC("glue"), BER_BVNULL };
 void glue_parent(Operation *op) {
        Operation nop = *op;
        slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
-       struct berval dn = { 0, NULL };
-       char *odn = op->o_req_ndn.bv_val;
+       struct berval ndn = BER_BVNULL;
        Attribute *a;
        Entry *e;
-       int idn, ldn;
+       struct berval   pdn;
 
-       /* tis more work to use strchr() for a berval... */
-       for(idn = 0; odn[idn] && odn[idn] != ','; idn++);
-       if(!idn || !odn[idn]) return;   /* because you never know */
-       idn++;
-       ldn = dn.bv_len = op->o_req_ndn.bv_len - idn;
-       dn.bv_val = ch_malloc(ldn + 1);
-       strcpy(dn.bv_val, odn + idn);
+       dnParent( &op->o_req_ndn, &pdn );
+       ber_dupbv_x( &ndn, &pdn, op->o_tmpmemctx );
 
-       Debug(LDAP_DEBUG_TRACE, "=> glue_parent: fabricating glue for <%s>\n", dn.bv_val, 0, 0);
+       Debug(LDAP_DEBUG_TRACE, "=> glue_parent: fabricating glue for <%s>\n", ndn.bv_val, 0, 0);
 
        e = ch_calloc(1, sizeof(Entry));
        e->e_id = NOID;
-       ber_dupbv(&e->e_name, &dn);
-       ber_dupbv(&e->e_nname, &dn);
+       ber_dupbv(&e->e_name, &ndn);
+       ber_dupbv(&e->e_nname, &ndn);
 
        a = ch_calloc(1, sizeof(Attribute));
        a->a_desc = slap_schema.si_ad_objectClass;
@@ -102,12 +97,15 @@ void glue_parent(Operation *op) {
        a->a_next = e->e_attrs;
        e->e_attrs = a;
 
-       nop.o_req_dn = dn;
-       nop.o_req_ndn = dn;
+       nop.o_req_dn = ndn;
+       nop.o_req_ndn = ndn;
        nop.ora_e = e;
        nop.o_bd->bd_info = (BackendInfo *) on->on_info->oi_orig;
 
        syncrepl_add_glue(&nop, e);
+
+       op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx );
+
        return;
 }
 
@@ -134,9 +132,9 @@ BerVarray dup_bervarray(BerVarray b) {
 */
 void free_attr_chain(Attribute *a) {
        Attribute *ax;
-       for(ax = NULL; a; a = a->a_next) {
-               if(ax) ch_free(ax);
-               ax = a;
+       for(; a; a = ax) {
+               ax = a->a_next;
+               ch_free(a);
        }
        return;
 }
@@ -207,6 +205,15 @@ static int translucent_delete(Operation *op, SlapReply *rs) {
        return(SLAP_CB_CONTINUE);
 }
 
+static int
+translucent_tag_cb( Operation *op, SlapReply *rs )
+{
+       op->o_tag = (ber_tag_t)op->o_callback->sc_private;
+       rs->sr_tag = slap_req2res( op->o_tag );
+
+       return SLAP_CB_CONTINUE;
+}
+
 /*
 ** translucent_modify()
 **     modify in local backend if exists in both;
@@ -222,10 +229,11 @@ static int translucent_modify(Operation *op, SlapReply *rs) {
        slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
        overlay_stack *ov = on->on_bi.bi_private;
        void *private = op->o_bd->be_private;
-       Entry ne, *e, *re = NULL;
+       Entry ne, *e = NULL, *re = NULL;
        Attribute *a, *ax;
        Modifications *m, *mm;
        int del, rc, erc = 0;
+       slap_callback cb = { 0 };
 
        Debug(LDAP_DEBUG_TRACE, "==> translucent_modify: %s\n",
                op->o_req_dn.bv_val, 0, 0);
@@ -243,7 +251,7 @@ static int translucent_modify(Operation *op, SlapReply *rs) {
        op->o_bd->be_private = private;
 
        /* if(ov->config->no_add && (!re || rc != LDAP_SUCCESS)) */
-       if(!re || rc != LDAP_SUCCESS) {
+       if(rc != LDAP_SUCCESS || re == NULL ) {
                send_ldap_error(op, rs, LDAP_NO_SUCH_OBJECT,
                        "attempt to modify nonexistent local record");
                return(rs->sr_err);
@@ -316,6 +324,15 @@ release:
                }
        }
 
+       /* don't leak remote entry copy */
+       if(re) {
+               op->o_bd->be_private = ov->private;
+               if(ov->info->bi_entry_release_rw)
+                       ov->info->bi_entry_release_rw(op, re, 0);
+               else
+                       entry_free(re);
+               op->o_bd->be_private = private;
+       }
 /*
 ** foreach Modification:
 **     if MOD_ADD or MOD_REPLACE, add Attribute;
@@ -382,6 +399,10 @@ release:
        op->o_bd->bd_info = (BackendInfo *) on;
        glue_parent(&nop);
 
+       cb.sc_response = translucent_tag_cb;
+       cb.sc_private = (void *)LDAP_REQ_MODIFY;
+       cb.sc_next = nop.o_callback;
+       nop.o_callback = &cb;
        rc = on->on_info->oi_orig->bi_op_add(&nop, &nrs);
        free_attr_chain(a);
 
@@ -563,13 +584,13 @@ static int translucent_bind(Operation *op, SlapReply *rs) {
 }
 
 /*
-** translucent_config()
+** translucent_db_config()
 **     pass config directives to captive backend;
 **     parse unrecognized directives ourselves;
 **
 */
 
-static int translucent_config(
+static int translucent_db_config(
        BackendDB       *be,
        const char      *fname,
        int             lineno,
@@ -610,7 +631,11 @@ static int translucent_config(
                        ov->config->debug = 0xFFFF;
                        rc = 0;
                } else if(argc == 2) {
-                       ov->config->debug = atoi(argv[1]);
+                       if ( lutil_atoi( &ov->config->debug, argv[1]) != 0 ) {
+                               fprintf(stderr, "%s: line %d: unable to parse debug \"%s\"\n",
+                                       fname, lineno, argv[1]);
+                               return 1;
+                       }
                        rc = 0;
                } else {
                        fprintf(stderr, "%s: line %d: too many arguments (%d) to debug\n",
@@ -664,12 +689,12 @@ static int translucent_db_init(BackendDB *be) {
 }
 
 /*
-** translucent_open()
+** translucent_db_open()
 **     if the captive backend has an open() method, call it;
 **
 */
 
-static int translucent_open(BackendDB *be) {
+static int translucent_db_open(BackendDB *be) {
        slap_overinst *on = (slap_overinst *) be->bd_info;
        overlay_stack *ov = on->on_bi.bi_private;
        void *private = be->be_private;
@@ -694,39 +719,68 @@ static int translucent_open(BackendDB *be) {
 }
 
 /*
-** translucent_close()
+** translucent_db_close()
 **     if the captive backend has a close() method, call it;
 **     free any config data;
 **
 */
 
-static int translucent_close(BackendDB *be) {
+static int translucent_db_close(BackendDB *be) {
        slap_overinst *on = (slap_overinst *) be->bd_info;
        overlay_stack *ov = on->on_bi.bi_private;
-       void *private = be->be_private;
-       int rc;
+       int rc = 0;
+
+       if ( ov ) {
+               void *private = be->be_private;
+
+               be->be_private = ov->private;
+               rc = (ov->info && ov->info->bi_db_close) ? ov->info->bi_db_close(be) : 0;
+               be->be_private = private;
+               if(ov->config) ch_free(ov->config);
+               ov->config = NULL;
+       }
+
+       return(rc);
+}
+
+/*
+** translucent_db_destroy()
+**     if the captive backend has a db_destroy() method, call it
+**
+*/
+
+static int translucent_db_destroy(BackendDB *be) {
+       slap_overinst *on = (slap_overinst *) be->bd_info;
+       overlay_stack *ov = on->on_bi.bi_private;
+       int rc = 0;
+
+       if ( ov ) {
+               void *private = be->be_private;
+
+               be->be_private = ov->private;
+               rc = (ov->info && ov->info->bi_db_destroy) ? ov->info->bi_db_destroy(be) : 0;
+               be->be_private = private;
+               ch_free(ov);
+               on->on_bi.bi_private = NULL;
+       }
 
-       be->be_private = ov->private;
-       rc = (ov->info && ov->info->bi_db_close) ? ov->info->bi_db_close(be) : 0;
-       be->be_private = private;
-       if(ov->config) ch_free(ov->config);
-       ch_free(ov);
        return(rc);
 }
 
 /*
-** translucent_init()
+** translucent_initialize()
 **     initialize the slap_overinst with our entry points;
 **
 */
 
-int translucent_init() {
+int translucent_initialize() {
 
        translucent.on_bi.bi_type       = "translucent";
        translucent.on_bi.bi_db_init    = translucent_db_init;
-       translucent.on_bi.bi_db_config  = translucent_config;
-       translucent.on_bi.bi_db_open    = translucent_open;
-       translucent.on_bi.bi_db_close   = translucent_close;
+       translucent.on_bi.bi_db_config  = translucent_db_config;
+       translucent.on_bi.bi_db_open    = translucent_db_open;
+       translucent.on_bi.bi_db_close   = translucent_db_close;
+       translucent.on_bi.bi_db_destroy = translucent_db_destroy;
        translucent.on_bi.bi_op_bind    = translucent_bind;
        translucent.on_bi.bi_op_add     = translucent_add;
        translucent.on_bi.bi_op_modify  = translucent_modify;
@@ -740,7 +794,7 @@ int translucent_init() {
 
 #if SLAPD_OVER_TRANSLUCENT == SLAPD_MOD_DYNAMIC && defined(PIC)
 int init_module(int argc, char *argv[]) {
-       return translucent_init();
+       return translucent_initialize();
 }
 #endif