| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916 |
- /** BEGIN COPYRIGHT BLOCK
- * This Program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation; version 2 of the License.
- *
- * This Program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * In addition, as a special exception, Red Hat, Inc. gives You the additional
- * right to link the code of this Program with code not covered under the GNU
- * General Public License ("Non-GPL Code") and to distribute linked combinations
- * including the two, subject to the limitations in this paragraph. Non-GPL Code
- * permitted under this exception must only link to the code of this Program
- * through those well defined interfaces identified in the file named EXCEPTION
- * found in the source code files (the "Approved Interfaces"). The files of
- * Non-GPL Code may instantiate templates or use macros or inline functions from
- * the Approved Interfaces without causing the resulting work to be covered by
- * the GNU General Public License. Only Red Hat, Inc. may make changes or
- * additions to the list of Approved Interfaces. You must obey the GNU General
- * Public License in all respects for all of the Program code and other code used
- * in conjunction with the Program except the Non-GPL Code covered by this
- * exception. If you modify this file, you may extend this exception to your
- * version of the file, but you are not obligated to do so. If you do not wish to
- * provide this exception without modification, you must delete this exception
- * statement from your version and license this file solely under the GPL without
- * exception.
- *
- *
- * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
- * Copyright (C) 2005 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK **/
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
- /*
- repl5_total.c - code that implements a total replica update.
- The requestValue of the NSDS50ReplicationEntry looks like this:
- requestValue ::= SEQUENCE {
- uniqueid OCTET STRING,
- dn LDAPDN,
- annotatedAttributes AnnotatedAttributeList
- }
- AnnotatedAttributeList ::= SET OF SEQUENCE {
- attributeType AttributeDescription,
- attributeDeletionCSN OCTET STRING OPTIONAL,
- attributeDeleted BOOLEAN DEFAULT FALSE,
- annotatedValues SET OF AnnotatedValue
- }
- AnnotatedValue ::= SEQUENCE {
- value AttributeValue,
- valueDeleted BOOLEAN DEFAULT FALSE,
- valueCSNSet SEQUENCE OF ValueCSN,
- }
- ValueCSN ::= SEQUENCE {
- CSNType ENUMERATED {
- valuePresenceCSN (1),
- valueDeletionCSN (2),
- valueDistinguishedCSN (3)
- }
- CSN OCTET STRING,
- }
- */
- #include "repl.h"
- #include "repl5.h"
- #define CSN_TYPE_VALUE_UPDATED_ON_WIRE 1
- #define CSN_TYPE_VALUE_DELETED_ON_WIRE 2
- #define CSN_TYPE_VALUE_DISTINGUISHED_ON_WIRE 3
- /* #define GORDONS_PATENTED_BER_DEBUG 1 */
- #ifdef GORDONS_PATENTED_BER_DEBUG
- #define BER_DEBUG(a) printf(a)
- #else
- #define BER_DEBUG(a)
- #endif
- /* Forward declarations */
- static int my_ber_printf_csn(BerElement *ber, const CSN *csn, const CSNType t);
- static int my_ber_printf_value(BerElement *ber, const char *type,
- const Slapi_Value *value, PRBool deleted);
- static int my_ber_printf_attr (BerElement *ber, Slapi_Attr *attr, PRBool deleted);
- static int my_ber_scanf_attr (BerElement *ber, Slapi_Attr **attr, PRBool *deleted);
- static int my_ber_scanf_value(BerElement *ber, Slapi_Value **value, PRBool *deleted);
- /*
- * Get a Slapi_Entry ready to send over the wire as part of
- * a total update protocol stream. Convert the entry and all
- * of its state information to a BerElement which will be the
- * payload of an extended LDAP operation.
- *
- * Entries consist of:
- * - An entry DN
- * - A uniqueID
- * - A set of present attributes, each of which consists of:
- * - A set of present values, each of which consists of:
- * - A value
- * - A set of CSNs
- * - A set of deleted values, each of which consists of:
- * - A value
- * - A set of CSNs
- * - A set of deleted attibutes, each of which consists of:
- * - An attribute type
- * - A set of CSNs. Note that this list of CSNs will always contain exactly one CSN.
- *
- * This all gets mashed into one BerElement, ready to be blasted over the wire to
- * a replica.
- *
- */
- BerElement *
- entry2bere(const Slapi_Entry *e, char **excluded_attrs)
- {
- BerElement *ber = NULL;
- const char *str = NULL;
- const char *dnstr = NULL;
- char *type;
- Slapi_DN *sdn = NULL;
- Slapi_Attr *attr = NULL, *prev_attr;
- int rc;
- PR_ASSERT(NULL != e);
- if ((ber = ber_alloc()) == NULL)
- {
- goto loser;
- }
- BER_DEBUG("{");
- if (ber_printf(ber, "{") == -1) /* Begin outer sequence */
- {
- goto loser;
- }
- /* Get the entry's uniqueid */
- if ((str = slapi_entry_get_uniqueid(e)) == NULL)
- {
- goto loser;
- }
- BER_DEBUG("s(uniqueid)");
- if (ber_printf(ber, "s", str) == -1)
- {
- goto loser;
- }
- /* Get the entry's DN */
- if ((sdn = slapi_entry_get_sdn((Slapi_Entry *)e)) == NULL) /* XXXggood had to cast away const */
- {
- goto loser;
- }
- if ((dnstr = slapi_sdn_get_dn(sdn)) == NULL)
- {
- goto loser;
- }
- BER_DEBUG("s(dn)");
- if (ber_printf(ber, "s", dnstr) == -1)
- {
- goto loser;
- }
- /* Next comes the annoted list of the entry's attributes */
- BER_DEBUG("[");
- if (ber_printf(ber, "[") == -1) /* Begin set of attributes */
- {
- goto loser;
- }
- /*
- * We iterate over all of the non-deleted attributes first.
- */
- slapi_entry_first_attr(e, &attr);
- while (NULL != attr)
- {
- /* ONREPL - skip uniqueid attribute since we already sent uniqueid
- This is a hack; need to figure a better way of storing uniqueid
- in an entry */
- slapi_attr_get_type (attr, &type);
- if (strcasecmp (type, SLAPI_ATTR_UNIQUEID) != 0)
- {
- /* Check to see if this attribute is excluded by the fractional list */
- if ( (NULL == excluded_attrs) || !charray_inlist(excluded_attrs,type))
- {
- /* Process this attribute */
- rc = my_ber_printf_attr (ber, attr, PR_FALSE);
- if (rc != 0)
- {
- goto loser;
- }
- }
- }
-
- prev_attr = attr;
- slapi_entry_next_attr(e, prev_attr, &attr);
- }
- /*
- * Now iterate over the deleted attributes.
- */
- entry_first_deleted_attribute(e, &attr);
- while (attr != NULL)
- {
- slapi_attr_get_type (attr, &type);
- /* Check to see if this attribute is excluded by the fractional list */
- if ( (NULL == excluded_attrs) || !charray_inlist(excluded_attrs,type))
- {
- /* Process this attribute */
- rc = my_ber_printf_attr (ber, attr, PR_TRUE);
- if (rc != 0)
- {
- goto loser;
- }
- }
- entry_next_deleted_attribute(e, &attr);
- }
- BER_DEBUG("]");
- if (ber_printf(ber, "]") == -1) /* End set for attributes */
- {
- goto loser;
- }
- BER_DEBUG("}");
- if (ber_printf(ber, "}") == -1) /* End sequence for this entry */
- {
- goto loser;
- }
-
- /* If we get here, everything went ok */
- BER_DEBUG("\n");
- goto free_and_return;
- loser:
- if (NULL != ber)
- {
- ber_free(ber, 1);
- ber = NULL;
- }
- free_and_return:
- return ber;
- }
- /*
- * Helper function - convert a CSN to a string and ber_printf() it.
- */
- static int
- my_ber_printf_csn(BerElement *ber, const CSN *csn, const CSNType t)
- {
- char csn_str[CSN_STRSIZE];
- int rc = -1;
- ber_int_t csn_type_as_ber = -1;
- switch (t)
- {
- case CSN_TYPE_VALUE_UPDATED:
- csn_type_as_ber = CSN_TYPE_VALUE_UPDATED_ON_WIRE;
- break;
- case CSN_TYPE_VALUE_DELETED:
- csn_type_as_ber = CSN_TYPE_VALUE_DELETED_ON_WIRE;
- break;
- case CSN_TYPE_VALUE_DISTINGUISHED:
- csn_type_as_ber = CSN_TYPE_VALUE_DISTINGUISHED_ON_WIRE;
- break;
- case CSN_TYPE_ATTRIBUTE_DELETED:
- break;
- default:
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_printf_csn: unknown "
- "csn type %d encountered.\n", (int)t);
- return -1;
- }
- csn_as_string(csn,PR_FALSE,csn_str);
- /* we don't send type for attr csn since there is only one */
- if (t == CSN_TYPE_ATTRIBUTE_DELETED)
- {
- rc = ber_printf(ber, "s", csn_str);
- BER_DEBUG("s(csn_str)");
- }
- else
- {
- rc = ber_printf(ber, "{es}", csn_type_as_ber, csn_str);
- BER_DEBUG("{e(csn type)s(csn)}");
- }
- return rc;
- }
- /*
- * Send a single annotated attribute value.
- */
- static int
- my_ber_printf_value(BerElement *ber, const char *type, const Slapi_Value *value, PRBool deleted)
- {
- const struct berval *bval = NULL;
- int rc = -1;
- const CSNSet *csnset;
- void *cookie;
- CSN *csn;
- CSNType t;
- bval = slapi_value_get_berval(value);
- BER_DEBUG("{o(value)");
- if (ber_printf(ber, "{o", bval->bv_val, bval->bv_len) == -1) /* Start sequence */
- {
- goto done;
- }
-
- /* if (ber_printf(ber, "o", bval->bv_val, bval->bv_len) == -1)
- {
- goto done;
- } */
- if (deleted)
- {
- BER_DEBUG("b(deleted flag)");
- if (ber_printf (ber, "b", PR_TRUE) == -1)
- {
- goto done;
- }
- }
- /* Send value CSN list */
- BER_DEBUG("{");
- if (ber_printf(ber, "{") == -1) /* Start set */
- {
- goto done;
- }
- /* Iterate over the sequence of CSNs. */
- csnset = value_get_csnset (value);
- if (csnset)
- {
- for (cookie = csnset_get_first_csn (csnset, &csn, &t); NULL != cookie;
- cookie = csnset_get_next_csn (csnset, cookie, &csn, &t))
- {
- /* Don't send any adcsns, since that was already sent */
- if (t != CSN_TYPE_ATTRIBUTE_DELETED)
- {
- if (my_ber_printf_csn(ber, csn, t) == -1)
- {
- goto done;
- }
- }
- }
- }
-
- BER_DEBUG("}");
- if (ber_printf(ber, "}") == -1) /* End CSN sequence */
- {
- goto done;
- }
- BER_DEBUG("}");
- if (ber_printf(ber, "}") == -1) /* End sequence */
- {
- goto done;
- }
- /* Everything's ok */
- rc = 0;
- done:
- return rc;
- }
- /* send a single attribute */
- static int
- my_ber_printf_attr (BerElement *ber, Slapi_Attr *attr, PRBool deleted)
- {
- Slapi_Value *value;
- char *type;
- int i;
- const CSN *csn;
-
- /* First, send the type */
- slapi_attr_get_type(attr, &type);
- BER_DEBUG("{s(type ");
- BER_DEBUG(type);
- BER_DEBUG(")");
- if (ber_printf(ber, "{s", type) == -1) /* Begin sequence for this type */
- {
- goto loser;
- }
- /* Send the attribute deletion CSN if present */
- csn = attr_get_deletion_csn(attr);
- if (csn)
- {
- if (my_ber_printf_csn(ber, csn, CSN_TYPE_ATTRIBUTE_DELETED) == -1)
- {
- goto loser;
- }
- }
- /* only send "is deleted" flag for deleted attributes since it defaults to false */
- if (deleted)
- {
- BER_DEBUG("b(del flag)");
- if (ber_printf (ber, "b", PR_TRUE) == -1)
- {
- goto loser;
- }
- }
- /*
- * Iterate through all the values.
- */
- BER_DEBUG("[");
- if (ber_printf(ber, "[") == -1) /* Begin set */
- {
- goto loser;
- }
-
- /*
- * Process the non-deleted values first.
- */
- i = slapi_attr_first_value(attr, &value);
- while (i != -1)
- {
- if (my_ber_printf_value(ber, type, value, PR_FALSE) == -1)
- {
- goto loser;
- }
- i= slapi_attr_next_value(attr, i, &value);
- }
- /*
- * Now iterate over all of the deleted values.
- */
- i= attr_first_deleted_value(attr, &value);
- while (i != -1)
- {
- if (my_ber_printf_value(ber, type, value, PR_TRUE) == -1)
- {
- goto loser;
- }
- i= attr_next_deleted_value(attr, i, &value);
- }
- BER_DEBUG("]");
- if (ber_printf(ber, "]") == -1) /* End set */
- {
- goto loser;
- }
- BER_DEBUG("}");
- if (ber_printf(ber, "}") == -1) /* End sequence for this type */
- {
- goto loser;
- }
- return 0;
- loser:
- return -1;
- }
- /*
- * Get an annotated value from the BerElement. Returns 0 on
- * success, -1 on failure.
- */
- static int
- my_ber_scanf_value(BerElement *ber, Slapi_Value **value, PRBool *deleted)
- {
- struct berval *attrval = NULL;
- ber_len_t len = -1;
- ber_tag_t tag;
- CSN *csn = NULL;
- char csnstring[CSN_STRSIZE + 1];
- CSNType csntype;
- char *lasti;
- PR_ASSERT(ber && value && deleted);
- *value = NULL;
- if (NULL == ber && NULL == value)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 1\n");
- goto loser;
- }
- /* Each value is a sequence */
- if (ber_scanf(ber, "{O", &attrval) == LBER_ERROR)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 2\n");
- goto loser;
- }
- /* Allocate and fill in the attribute value */
- if ((*value = slapi_value_new_berval(attrval)) == NULL)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 3\n");
- goto loser;
- }
- /* check if this is a deleted value */
- if (ber_peek_tag(ber, &len) == LBER_BOOLEAN)
- {
- if (ber_scanf(ber, "b", deleted) == LBER_ERROR)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 4\n");
- goto loser;
- }
- }
-
- else /* default is present value */
- {
- *deleted = PR_FALSE;
- }
- /* Read the sequence of CSNs */
- for (tag = ber_first_element(ber, &len, &lasti);
- tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET;
- tag = ber_next_element(ber, &len, lasti))
- {
- ber_int_t csntype_tmp;
- /* Each CSN is in a sequence that includes a csntype and CSN */
- len = CSN_STRSIZE;
- if (ber_scanf(ber, "{es}", &csntype_tmp, csnstring, &len) == LBER_ERROR)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 7 - bval is %s\n", attrval->bv_val);
- goto loser;
- }
- switch (csntype_tmp)
- {
- case CSN_TYPE_VALUE_UPDATED_ON_WIRE:
- csntype = CSN_TYPE_VALUE_UPDATED;
- break;
- case CSN_TYPE_VALUE_DELETED_ON_WIRE:
- csntype = CSN_TYPE_VALUE_DELETED;
- break;
- case CSN_TYPE_VALUE_DISTINGUISHED_ON_WIRE:
- csntype = CSN_TYPE_VALUE_DISTINGUISHED;
- break;
- default:
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Error: preposterous CSN type "
- "%d received during total update.\n", csntype_tmp);
- goto loser;
- }
- csn = csn_new_by_string(csnstring);
- if (csn == NULL)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 8\n");
- goto loser;
- }
- value_add_csn(*value, csntype, csn);
- csn_free (&csn);
- }
- if (ber_scanf(ber, "}") == LBER_ERROR) /* End of annotated attribute value seq */
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 10\n");
- goto loser;
- }
-
- if (attrval)
- ber_bvfree(attrval);
- return 0;
- loser:
- /* Free any stuff we allocated */
- if (csn)
- csn_free (&csn);
- if (attrval)
- ber_bvfree(attrval);
- if (value)
- {
- slapi_value_free (value);
- }
-
- return -1;
- }
- static int
- my_ber_scanf_attr (BerElement *ber, Slapi_Attr **attr, PRBool *deleted)
- {
- char *attrtype = NULL;
- CSN *attr_deletion_csn = NULL;
- PRBool val_deleted;
- char *lasti;
- ber_len_t len;
- ber_tag_t tag;
- char *str = NULL;
- int rc;
- Slapi_Value *value;
- PR_ASSERT (ber && attr && deleted);
- /* allocate the attribute */
- *attr = slapi_attr_new ();
- if (attr == NULL)
- {
- goto loser;
- }
- if (ber_scanf(ber, "{a", &attrtype) == LBER_ERROR) /* Begin sequence for this attr */
- {
- goto loser;
- }
- slapi_attr_init(*attr, attrtype);
- slapi_ch_free ((void **)&attrtype);
- /* The attribute deletion CSN is next and is optional? */
- if (ber_peek_tag(ber, &len) == LBER_OCTETSTRING)
- {
- if (ber_scanf(ber, "a", &str) == LBER_ERROR)
- {
- goto loser;
- }
- attr_deletion_csn = csn_new_by_string(str);
- slapi_ch_free((void **)&str);
- }
- if (attr_deletion_csn)
- {
- rc = attr_set_deletion_csn(*attr, attr_deletion_csn);
- csn_free (&attr_deletion_csn);
- if (rc != 0)
- {
- goto loser;
- }
- }
- /* The "attribute deleted" flag is next, and is optional */
- if (ber_peek_tag(ber, &len) == LBER_BOOLEAN)
- {
- if (ber_scanf(ber, "b", deleted) == LBER_DEFAULT)
- {
- goto loser;
- }
- }
- else /* default is present */
- {
- *deleted = PR_FALSE;
- }
-
- /* loop over the list of attribute values */
- for (tag = ber_first_element(ber, &len, &lasti);
- tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET;
- tag = ber_next_element(ber, &len, lasti))
- {
- value = NULL;
- if (my_ber_scanf_value(ber, &value, &val_deleted) == -1)
- {
- goto loser;
- }
- if (val_deleted)
- {
- /* Add the value to the attribute */
- if (attr_add_deleted_value(*attr, value) == -1) /* attr has ownership of value */
- {
- goto loser;
- }
- }
- else
- {
- /* Add the value to the attribute */
- if (slapi_attr_add_value(*attr, value) == -1) /* attr has ownership of value */
- {
- goto loser;
- }
- }
- if (value)
- slapi_value_free(&value);
- }
- if (ber_scanf(ber, "}") == LBER_ERROR) /* End sequence for this attribute */
- {
- goto loser;
- }
- return 0;
- loser:
- if (*attr)
- slapi_attr_free (attr);
- if (value)
- slapi_value_free (&value);
- slapi_ch_free_string(&attrtype);
- slapi_ch_free_string(&str);
- return -1;
- }
- /*
- * Extract the payload from a total update extended operation,
- * decode it, and produce a Slapi_Entry structure representing a new
- * entry to be added to the local database.
- */
- static int
- decode_total_update_extop(Slapi_PBlock *pb, Slapi_Entry **ep)
- {
- BerElement *tmp_bere = NULL;
- Slapi_Entry *e = NULL;
- Slapi_Attr *attr = NULL;
- char *str = NULL;
- CSN *dn_csn = NULL;
- struct berval *extop_value = NULL;
- char *extop_oid = NULL;
- ber_len_t len;
- char *lasto;
- ber_tag_t tag;
- int rc;
- PRBool deleted;
-
- PR_ASSERT(NULL != pb);
- PR_ASSERT(NULL != ep);
- slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_OID, &extop_oid);
- slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_value);
- if (NULL == extop_oid ||
- ((strcmp(extop_oid, REPL_NSDS50_REPLICATION_ENTRY_REQUEST_OID) != 0) &&
- (strcmp(extop_oid, REPL_NSDS71_REPLICATION_ENTRY_REQUEST_OID) != 0)) ||
- NULL == extop_value)
- {
- /* Bogus */
- goto loser;
- }
- if ((tmp_bere = ber_init(extop_value)) == NULL)
- {
- goto loser;
- }
- if ((e = slapi_entry_alloc()) == NULL)
- {
- goto loser;
- }
- if (ber_scanf(tmp_bere, "{") == LBER_ERROR) /* Begin outer sequence */
- {
- goto loser;
- }
- /* The entry's uniqueid is first */
- if (ber_scanf(tmp_bere, "a", &str) == LBER_ERROR)
- {
- goto loser;
- }
- slapi_entry_set_uniqueid(e, str);
- str = NULL; /* Slapi_Entry now owns the uniqueid */
- /* The entry's DN is next */
- if (ber_scanf(tmp_bere, "a", &str) == LBER_ERROR)
- {
- goto loser;
- }
- slapi_entry_set_dn(e, str);
- str = NULL; /* Slapi_Entry now owns the dn */
- /* Get the attributes */
- for ( tag = ber_first_element( tmp_bere, &len, &lasto );
- tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET;
- tag = ber_next_element( tmp_bere, &len, lasto ) )
- {
- if (my_ber_scanf_attr (tmp_bere, &attr, &deleted) != 0)
- {
- goto loser;
- }
-
- /* Add the attribute to the entry */
- if (deleted)
- entry_add_deleted_attribute_wsi(e, attr); /* entry now owns attr */
- else
- entry_add_present_attribute_wsi(e, attr); /* entry now owns attr */
- attr = NULL;
- }
- if (ber_scanf(tmp_bere, "}") == LBER_ERROR) /* End sequence for this entry */
- {
- goto loser;
- }
- /* Check for ldapsubentries and tombstone entries to set flags properly */
- slapi_entry_attr_find(e, "objectclass", &attr);
- if (attr != NULL) {
- struct berval bv;
- bv.bv_val = "ldapsubentry";
- bv.bv_len = strlen(bv.bv_val);
- if (slapi_attr_value_find(attr, &bv) == 0) {
- slapi_entry_set_flag(e, SLAPI_ENTRY_LDAPSUBENTRY);
- }
- bv.bv_val = SLAPI_ATTR_VALUE_TOMBSTONE;
- bv.bv_len = strlen(bv.bv_val);
- if (slapi_attr_value_find(attr, &bv) == 0) {
- slapi_entry_set_flag(e, SLAPI_ENTRY_FLAG_TOMBSTONE);
- }
- }
-
- /* If we get here, the entry is properly constructed. Return it. */
- rc = 0;
- *ep = e;
- goto free_and_return;
- loser:
- rc = -1;
- /* slapi_ch_free accepts NULL pointer */
- slapi_ch_free((void **)&str);
- if (NULL != dn_csn)
- {
- csn_free(&dn_csn);
- }
- if (attr != NULL)
- {
- slapi_attr_free (&attr);
- }
-
- if (NULL != e)
- {
- slapi_entry_free (e);
- }
- *ep = NULL;
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Error: could not decode extended "
- "operation containing entry for total update.\n");
- free_and_return:
- if (NULL != tmp_bere)
- {
- ber_free(tmp_bere, 1);
- tmp_bere = NULL;
- }
- return rc;
- }
- /*
- * This plugin entry point is called whenever an NSDS50ReplicationEntry
- * extended operation is received.
- */
- int
- multimaster_extop_NSDS50ReplicationEntry(Slapi_PBlock *pb)
- {
- int rc;
- Slapi_Entry *e = NULL;
- Slapi_Connection *conn = NULL;
- PRUint64 connid = 0;
- int opid = 0;
-
- slapi_pblock_get(pb, SLAPI_CONN_ID, &connid);
- slapi_pblock_get(pb, SLAPI_OPERATION_ID, &opid);
- /* Decode the extended operation */
- rc = decode_total_update_extop(pb, &e);
- if (0 == rc)
- {
- #ifdef notdef
- /*
- * Just spew LDIF so we're sure we got it right. Later we'll firehose
- * this into the database import code
- */
- int len;
- char *str = slapi_entry2str_with_options(e, &len,SLAPI_DUMP_UNIQUEID);
- puts(str);
- free(str);
- #endif
- rc = slapi_import_entry (pb, e);
- /* slapi_import_entry returns an LDAP error in case of a
- * problem. If there's a problem, it's our responsibility
- * to free the slapi_entry that we're trying to import.
- */
- if (rc != LDAP_SUCCESS)
- {
- const char *dn = slapi_entry_get_dn_const(e);
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
- "Error %d: could not import entry dn %s "
- "for total update operation conn=%" NSPRIu64 " op=%d\n",
- rc, dn, connid, opid);
- rc = -1;
- }
-
- }
- else
- {
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
- "Error %d: could not decode the total update extop "
- "for total update operation conn=%" NSPRIu64 " op=%d\n",
- rc, connid, opid);
- }
-
- if (rc != 0)
- {
- /* just disconnect from the supplier. bulk import is stopped when
- connection object is destroyed */
- slapi_pblock_get (pb, SLAPI_CONNECTION, &conn);
- if (conn)
- {
- slapi_disconnect_server(conn);
- }
- /* cleanup */
- if (e)
- {
- slapi_entry_free (e);
- }
- }
- return rc;
- }
|