repl5_total.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. #ifdef HAVE_CONFIG_H
  39. # include <config.h>
  40. #endif
  41. /*
  42. repl5_total.c - code that implements a total replica update.
  43. The requestValue of the NSDS50ReplicationEntry looks like this:
  44. requestValue ::= SEQUENCE {
  45. uniqueid OCTET STRING,
  46. dn LDAPDN,
  47. annotatedAttributes AnnotatedAttributeList
  48. }
  49. AnnotatedAttributeList ::= SET OF SEQUENCE {
  50. attributeType AttributeDescription,
  51. attributeDeletionCSN OCTET STRING OPTIONAL,
  52. attributeDeleted BOOLEAN DEFAULT FALSE,
  53. annotatedValues SET OF AnnotatedValue
  54. }
  55. AnnotatedValue ::= SEQUENCE {
  56. value AttributeValue,
  57. valueDeleted BOOLEAN DEFAULT FALSE,
  58. valueCSNSet SEQUENCE OF ValueCSN,
  59. }
  60. ValueCSN ::= SEQUENCE {
  61. CSNType ENUMERATED {
  62. valuePresenceCSN (1),
  63. valueDeletionCSN (2),
  64. valueDistinguishedCSN (3)
  65. }
  66. CSN OCTET STRING,
  67. }
  68. */
  69. #include "repl.h"
  70. #include "repl5.h"
  71. #define CSN_TYPE_VALUE_UPDATED_ON_WIRE 1
  72. #define CSN_TYPE_VALUE_DELETED_ON_WIRE 2
  73. #define CSN_TYPE_VALUE_DISTINGUISHED_ON_WIRE 3
  74. /* #define GORDONS_PATENTED_BER_DEBUG 1 */
  75. #ifdef GORDONS_PATENTED_BER_DEBUG
  76. #define BER_DEBUG(a) printf(a)
  77. #else
  78. #define BER_DEBUG(a)
  79. #endif
  80. /* Forward declarations */
  81. static int my_ber_printf_csn(BerElement *ber, const CSN *csn, const CSNType t);
  82. static int my_ber_printf_value(BerElement *ber, const char *type,
  83. const Slapi_Value *value, PRBool deleted);
  84. static int my_ber_printf_attr (BerElement *ber, Slapi_Attr *attr, PRBool deleted);
  85. static int my_ber_scanf_attr (BerElement *ber, Slapi_Attr **attr, PRBool *deleted);
  86. static int my_ber_scanf_value(BerElement *ber, Slapi_Value **value, PRBool *deleted);
  87. /*
  88. * Get a Slapi_Entry ready to send over the wire as part of
  89. * a total update protocol stream. Convert the entry and all
  90. * of its state information to a BerElement which will be the
  91. * payload of an extended LDAP operation.
  92. *
  93. * Entries consist of:
  94. * - An entry DN
  95. * - A uniqueID
  96. * - A set of present attributes, each of which consists of:
  97. * - A set of present values, each of which consists of:
  98. * - A value
  99. * - A set of CSNs
  100. * - A set of deleted values, each of which consists of:
  101. * - A value
  102. * - A set of CSNs
  103. * - A set of deleted attibutes, each of which consists of:
  104. * - An attribute type
  105. * - A set of CSNs. Note that this list of CSNs will always contain exactly one CSN.
  106. *
  107. * This all gets mashed into one BerElement, ready to be blasted over the wire to
  108. * a replica.
  109. *
  110. */
  111. BerElement *
  112. entry2bere(const Slapi_Entry *e, char **excluded_attrs)
  113. {
  114. BerElement *ber = NULL;
  115. const char *str = NULL;
  116. const char *dnstr = NULL;
  117. char *type;
  118. Slapi_DN *sdn = NULL;
  119. Slapi_Attr *attr = NULL, *prev_attr;
  120. int rc;
  121. PR_ASSERT(NULL != e);
  122. if ((ber = ber_alloc()) == NULL)
  123. {
  124. goto loser;
  125. }
  126. BER_DEBUG("{");
  127. if (ber_printf(ber, "{") == -1) /* Begin outer sequence */
  128. {
  129. goto loser;
  130. }
  131. /* Get the entry's uniqueid */
  132. if ((str = slapi_entry_get_uniqueid(e)) == NULL)
  133. {
  134. goto loser;
  135. }
  136. BER_DEBUG("s(uniqueid)");
  137. if (ber_printf(ber, "s", str) == -1)
  138. {
  139. goto loser;
  140. }
  141. /* Get the entry's DN */
  142. if ((sdn = slapi_entry_get_sdn((Slapi_Entry *)e)) == NULL) /* XXXggood had to cast away const */
  143. {
  144. goto loser;
  145. }
  146. if ((dnstr = slapi_sdn_get_dn(sdn)) == NULL)
  147. {
  148. goto loser;
  149. }
  150. BER_DEBUG("s(dn)");
  151. if (ber_printf(ber, "s", dnstr) == -1)
  152. {
  153. goto loser;
  154. }
  155. /* Next comes the annoted list of the entry's attributes */
  156. BER_DEBUG("[");
  157. if (ber_printf(ber, "[") == -1) /* Begin set of attributes */
  158. {
  159. goto loser;
  160. }
  161. /*
  162. * We iterate over all of the non-deleted attributes first.
  163. */
  164. slapi_entry_first_attr(e, &attr);
  165. while (NULL != attr)
  166. {
  167. /* ONREPL - skip uniqueid attribute since we already sent uniqueid
  168. This is a hack; need to figure a better way of storing uniqueid
  169. in an entry */
  170. slapi_attr_get_type (attr, &type);
  171. if (strcasecmp (type, SLAPI_ATTR_UNIQUEID) != 0)
  172. {
  173. /* Check to see if this attribute is excluded by the fractional list */
  174. if ( (NULL == excluded_attrs) || !charray_inlist(excluded_attrs,type))
  175. {
  176. /* Process this attribute */
  177. rc = my_ber_printf_attr (ber, attr, PR_FALSE);
  178. if (rc != 0)
  179. {
  180. goto loser;
  181. }
  182. }
  183. }
  184. prev_attr = attr;
  185. slapi_entry_next_attr(e, prev_attr, &attr);
  186. }
  187. /*
  188. * Now iterate over the deleted attributes.
  189. */
  190. entry_first_deleted_attribute(e, &attr);
  191. while (attr != NULL)
  192. {
  193. slapi_attr_get_type (attr, &type);
  194. /* Check to see if this attribute is excluded by the fractional list */
  195. if ( (NULL == excluded_attrs) || !charray_inlist(excluded_attrs,type))
  196. {
  197. /* Process this attribute */
  198. rc = my_ber_printf_attr (ber, attr, PR_TRUE);
  199. if (rc != 0)
  200. {
  201. goto loser;
  202. }
  203. }
  204. entry_next_deleted_attribute(e, &attr);
  205. }
  206. BER_DEBUG("]");
  207. if (ber_printf(ber, "]") == -1) /* End set for attributes */
  208. {
  209. goto loser;
  210. }
  211. BER_DEBUG("}");
  212. if (ber_printf(ber, "}") == -1) /* End sequence for this entry */
  213. {
  214. goto loser;
  215. }
  216. /* If we get here, everything went ok */
  217. BER_DEBUG("\n");
  218. goto free_and_return;
  219. loser:
  220. if (NULL != ber)
  221. {
  222. ber_free(ber, 1);
  223. ber = NULL;
  224. }
  225. free_and_return:
  226. return ber;
  227. }
  228. /*
  229. * Helper function - convert a CSN to a string and ber_printf() it.
  230. */
  231. static int
  232. my_ber_printf_csn(BerElement *ber, const CSN *csn, const CSNType t)
  233. {
  234. char csn_str[CSN_STRSIZE];
  235. int rc = -1;
  236. ber_int_t csn_type_as_ber = -1;
  237. switch (t)
  238. {
  239. case CSN_TYPE_VALUE_UPDATED:
  240. csn_type_as_ber = CSN_TYPE_VALUE_UPDATED_ON_WIRE;
  241. break;
  242. case CSN_TYPE_VALUE_DELETED:
  243. csn_type_as_ber = CSN_TYPE_VALUE_DELETED_ON_WIRE;
  244. break;
  245. case CSN_TYPE_VALUE_DISTINGUISHED:
  246. csn_type_as_ber = CSN_TYPE_VALUE_DISTINGUISHED_ON_WIRE;
  247. break;
  248. case CSN_TYPE_ATTRIBUTE_DELETED:
  249. break;
  250. default:
  251. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_printf_csn: unknown "
  252. "csn type %d encountered.\n", (int)t);
  253. return -1;
  254. }
  255. csn_as_string(csn,PR_FALSE,csn_str);
  256. /* we don't send type for attr csn since there is only one */
  257. if (t == CSN_TYPE_ATTRIBUTE_DELETED)
  258. {
  259. rc = ber_printf(ber, "s", csn_str);
  260. BER_DEBUG("s(csn_str)");
  261. }
  262. else
  263. {
  264. rc = ber_printf(ber, "{es}", csn_type_as_ber, csn_str);
  265. BER_DEBUG("{e(csn type)s(csn)}");
  266. }
  267. return rc;
  268. }
  269. /*
  270. * Send a single annotated attribute value.
  271. */
  272. static int
  273. my_ber_printf_value(BerElement *ber, const char *type, const Slapi_Value *value, PRBool deleted)
  274. {
  275. const struct berval *bval = NULL;
  276. int rc = -1;
  277. const CSNSet *csnset;
  278. void *cookie;
  279. CSN *csn;
  280. CSNType t;
  281. bval = slapi_value_get_berval(value);
  282. BER_DEBUG("{o(value)");
  283. if (ber_printf(ber, "{o", bval->bv_val, bval->bv_len) == -1) /* Start sequence */
  284. {
  285. goto done;
  286. }
  287. /* if (ber_printf(ber, "o", bval->bv_val, bval->bv_len) == -1)
  288. {
  289. goto done;
  290. } */
  291. if (deleted)
  292. {
  293. BER_DEBUG("b(deleted flag)");
  294. if (ber_printf (ber, "b", PR_TRUE) == -1)
  295. {
  296. goto done;
  297. }
  298. }
  299. /* Send value CSN list */
  300. BER_DEBUG("{");
  301. if (ber_printf(ber, "{") == -1) /* Start set */
  302. {
  303. goto done;
  304. }
  305. /* Iterate over the sequence of CSNs. */
  306. csnset = value_get_csnset (value);
  307. if (csnset)
  308. {
  309. for (cookie = csnset_get_first_csn (csnset, &csn, &t); NULL != cookie;
  310. cookie = csnset_get_next_csn (csnset, cookie, &csn, &t))
  311. {
  312. /* Don't send any adcsns, since that was already sent */
  313. if (t != CSN_TYPE_ATTRIBUTE_DELETED)
  314. {
  315. if (my_ber_printf_csn(ber, csn, t) == -1)
  316. {
  317. goto done;
  318. }
  319. }
  320. }
  321. }
  322. BER_DEBUG("}");
  323. if (ber_printf(ber, "}") == -1) /* End CSN sequence */
  324. {
  325. goto done;
  326. }
  327. BER_DEBUG("}");
  328. if (ber_printf(ber, "}") == -1) /* End sequence */
  329. {
  330. goto done;
  331. }
  332. /* Everything's ok */
  333. rc = 0;
  334. done:
  335. return rc;
  336. }
  337. /* send a single attribute */
  338. static int
  339. my_ber_printf_attr (BerElement *ber, Slapi_Attr *attr, PRBool deleted)
  340. {
  341. Slapi_Value *value;
  342. char *type;
  343. int i;
  344. const CSN *csn;
  345. /* First, send the type */
  346. slapi_attr_get_type(attr, &type);
  347. BER_DEBUG("{s(type ");
  348. BER_DEBUG(type);
  349. BER_DEBUG(")");
  350. if (ber_printf(ber, "{s", type) == -1) /* Begin sequence for this type */
  351. {
  352. goto loser;
  353. }
  354. /* Send the attribute deletion CSN if present */
  355. csn = attr_get_deletion_csn(attr);
  356. if (csn)
  357. {
  358. if (my_ber_printf_csn(ber, csn, CSN_TYPE_ATTRIBUTE_DELETED) == -1)
  359. {
  360. goto loser;
  361. }
  362. }
  363. /* only send "is deleted" flag for deleted attributes since it defaults to false */
  364. if (deleted)
  365. {
  366. BER_DEBUG("b(del flag)");
  367. if (ber_printf (ber, "b", PR_TRUE) == -1)
  368. {
  369. goto loser;
  370. }
  371. }
  372. /*
  373. * Iterate through all the values.
  374. */
  375. BER_DEBUG("[");
  376. if (ber_printf(ber, "[") == -1) /* Begin set */
  377. {
  378. goto loser;
  379. }
  380. /*
  381. * Process the non-deleted values first.
  382. */
  383. i = slapi_attr_first_value(attr, &value);
  384. while (i != -1)
  385. {
  386. if (my_ber_printf_value(ber, type, value, PR_FALSE) == -1)
  387. {
  388. goto loser;
  389. }
  390. i= slapi_attr_next_value(attr, i, &value);
  391. }
  392. /*
  393. * Now iterate over all of the deleted values.
  394. */
  395. i= attr_first_deleted_value(attr, &value);
  396. while (i != -1)
  397. {
  398. if (my_ber_printf_value(ber, type, value, PR_TRUE) == -1)
  399. {
  400. goto loser;
  401. }
  402. i= attr_next_deleted_value(attr, i, &value);
  403. }
  404. BER_DEBUG("]");
  405. if (ber_printf(ber, "]") == -1) /* End set */
  406. {
  407. goto loser;
  408. }
  409. BER_DEBUG("}");
  410. if (ber_printf(ber, "}") == -1) /* End sequence for this type */
  411. {
  412. goto loser;
  413. }
  414. return 0;
  415. loser:
  416. return -1;
  417. }
  418. /*
  419. * Get an annotated value from the BerElement. Returns 0 on
  420. * success, -1 on failure.
  421. */
  422. static int
  423. my_ber_scanf_value(BerElement *ber, Slapi_Value **value, PRBool *deleted)
  424. {
  425. struct berval *attrval = NULL;
  426. ber_len_t len = -1;
  427. ber_tag_t tag;
  428. CSN *csn = NULL;
  429. char csnstring[CSN_STRSIZE + 1];
  430. CSNType csntype;
  431. char *lasti;
  432. PR_ASSERT(ber && value && deleted);
  433. *value = NULL;
  434. if (NULL == ber && NULL == value)
  435. {
  436. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 1\n");
  437. goto loser;
  438. }
  439. /* Each value is a sequence */
  440. if (ber_scanf(ber, "{O", &attrval) == LBER_ERROR)
  441. {
  442. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 2\n");
  443. goto loser;
  444. }
  445. /* Allocate and fill in the attribute value */
  446. if ((*value = slapi_value_new_berval(attrval)) == NULL)
  447. {
  448. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 3\n");
  449. goto loser;
  450. }
  451. /* check if this is a deleted value */
  452. if (ber_peek_tag(ber, &len) == LBER_BOOLEAN)
  453. {
  454. if (ber_scanf(ber, "b", deleted) == LBER_ERROR)
  455. {
  456. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 4\n");
  457. goto loser;
  458. }
  459. }
  460. else /* default is present value */
  461. {
  462. *deleted = PR_FALSE;
  463. }
  464. /* Read the sequence of CSNs */
  465. for (tag = ber_first_element(ber, &len, &lasti);
  466. tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET;
  467. tag = ber_next_element(ber, &len, lasti))
  468. {
  469. ber_int_t csntype_tmp;
  470. /* Each CSN is in a sequence that includes a csntype and CSN */
  471. len = CSN_STRSIZE;
  472. if (ber_scanf(ber, "{es}", &csntype_tmp, csnstring, &len) == LBER_ERROR)
  473. {
  474. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 7 - bval is %s\n", attrval->bv_val);
  475. goto loser;
  476. }
  477. switch (csntype_tmp)
  478. {
  479. case CSN_TYPE_VALUE_UPDATED_ON_WIRE:
  480. csntype = CSN_TYPE_VALUE_UPDATED;
  481. break;
  482. case CSN_TYPE_VALUE_DELETED_ON_WIRE:
  483. csntype = CSN_TYPE_VALUE_DELETED;
  484. break;
  485. case CSN_TYPE_VALUE_DISTINGUISHED_ON_WIRE:
  486. csntype = CSN_TYPE_VALUE_DISTINGUISHED;
  487. break;
  488. default:
  489. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Error: preposterous CSN type "
  490. "%d received during total update.\n", csntype_tmp);
  491. goto loser;
  492. }
  493. csn = csn_new_by_string(csnstring);
  494. if (csn == NULL)
  495. {
  496. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 8\n");
  497. goto loser;
  498. }
  499. value_add_csn(*value, csntype, csn);
  500. csn_free (&csn);
  501. }
  502. if (ber_scanf(ber, "}") == LBER_ERROR) /* End of annotated attribute value seq */
  503. {
  504. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 10\n");
  505. goto loser;
  506. }
  507. if (attrval)
  508. ber_bvfree(attrval);
  509. return 0;
  510. loser:
  511. /* Free any stuff we allocated */
  512. if (csn)
  513. csn_free (&csn);
  514. if (attrval)
  515. ber_bvfree(attrval);
  516. if (value)
  517. {
  518. slapi_value_free (value);
  519. }
  520. return -1;
  521. }
  522. static int
  523. my_ber_scanf_attr (BerElement *ber, Slapi_Attr **attr, PRBool *deleted)
  524. {
  525. char *attrtype = NULL;
  526. CSN *attr_deletion_csn = NULL;
  527. PRBool val_deleted;
  528. char *lasti;
  529. ber_len_t len;
  530. ber_tag_t tag;
  531. char *str = NULL;
  532. int rc;
  533. Slapi_Value *value;
  534. PR_ASSERT (ber && attr && deleted);
  535. /* allocate the attribute */
  536. *attr = slapi_attr_new ();
  537. if (attr == NULL)
  538. {
  539. goto loser;
  540. }
  541. if (ber_scanf(ber, "{a", &attrtype) == LBER_ERROR) /* Begin sequence for this attr */
  542. {
  543. goto loser;
  544. }
  545. slapi_attr_init(*attr, attrtype);
  546. slapi_ch_free ((void **)&attrtype);
  547. /* The attribute deletion CSN is next and is optional? */
  548. if (ber_peek_tag(ber, &len) == LBER_OCTETSTRING)
  549. {
  550. if (ber_scanf(ber, "a", &str) == LBER_ERROR)
  551. {
  552. goto loser;
  553. }
  554. attr_deletion_csn = csn_new_by_string(str);
  555. slapi_ch_free((void **)&str);
  556. }
  557. if (attr_deletion_csn)
  558. {
  559. rc = attr_set_deletion_csn(*attr, attr_deletion_csn);
  560. csn_free (&attr_deletion_csn);
  561. if (rc != 0)
  562. {
  563. goto loser;
  564. }
  565. }
  566. /* The "attribute deleted" flag is next, and is optional */
  567. if (ber_peek_tag(ber, &len) == LBER_BOOLEAN)
  568. {
  569. if (ber_scanf(ber, "b", deleted) == LBER_DEFAULT)
  570. {
  571. goto loser;
  572. }
  573. }
  574. else /* default is present */
  575. {
  576. *deleted = PR_FALSE;
  577. }
  578. /* loop over the list of attribute values */
  579. for (tag = ber_first_element(ber, &len, &lasti);
  580. tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET;
  581. tag = ber_next_element(ber, &len, lasti))
  582. {
  583. value = NULL;
  584. if (my_ber_scanf_value(ber, &value, &val_deleted) == -1)
  585. {
  586. goto loser;
  587. }
  588. if (val_deleted)
  589. {
  590. /* Add the value to the attribute */
  591. if (attr_add_deleted_value(*attr, value) == -1) /* attr has ownership of value */
  592. {
  593. goto loser;
  594. }
  595. }
  596. else
  597. {
  598. /* Add the value to the attribute */
  599. if (slapi_attr_add_value(*attr, value) == -1) /* attr has ownership of value */
  600. {
  601. goto loser;
  602. }
  603. }
  604. if (value)
  605. slapi_value_free(&value);
  606. }
  607. if (ber_scanf(ber, "}") == LBER_ERROR) /* End sequence for this attribute */
  608. {
  609. goto loser;
  610. }
  611. return 0;
  612. loser:
  613. if (*attr)
  614. slapi_attr_free (attr);
  615. if (value)
  616. slapi_value_free (&value);
  617. slapi_ch_free_string(&attrtype);
  618. slapi_ch_free_string(&str);
  619. return -1;
  620. }
  621. /*
  622. * Extract the payload from a total update extended operation,
  623. * decode it, and produce a Slapi_Entry structure representing a new
  624. * entry to be added to the local database.
  625. */
  626. static int
  627. decode_total_update_extop(Slapi_PBlock *pb, Slapi_Entry **ep)
  628. {
  629. BerElement *tmp_bere = NULL;
  630. Slapi_Entry *e = NULL;
  631. Slapi_Attr *attr = NULL;
  632. char *str = NULL;
  633. CSN *dn_csn = NULL;
  634. struct berval *extop_value = NULL;
  635. char *extop_oid = NULL;
  636. ber_len_t len;
  637. char *lasto;
  638. ber_tag_t tag;
  639. int rc;
  640. PRBool deleted;
  641. PR_ASSERT(NULL != pb);
  642. PR_ASSERT(NULL != ep);
  643. slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_OID, &extop_oid);
  644. slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_value);
  645. if (NULL == extop_oid ||
  646. ((strcmp(extop_oid, REPL_NSDS50_REPLICATION_ENTRY_REQUEST_OID) != 0) &&
  647. (strcmp(extop_oid, REPL_NSDS71_REPLICATION_ENTRY_REQUEST_OID) != 0)) ||
  648. NULL == extop_value)
  649. {
  650. /* Bogus */
  651. goto loser;
  652. }
  653. if ((tmp_bere = ber_init(extop_value)) == NULL)
  654. {
  655. goto loser;
  656. }
  657. if ((e = slapi_entry_alloc()) == NULL)
  658. {
  659. goto loser;
  660. }
  661. if (ber_scanf(tmp_bere, "{") == LBER_ERROR) /* Begin outer sequence */
  662. {
  663. goto loser;
  664. }
  665. /* The entry's uniqueid is first */
  666. if (ber_scanf(tmp_bere, "a", &str) == LBER_ERROR)
  667. {
  668. goto loser;
  669. }
  670. slapi_entry_set_uniqueid(e, str);
  671. str = NULL; /* Slapi_Entry now owns the uniqueid */
  672. /* The entry's DN is next */
  673. if (ber_scanf(tmp_bere, "a", &str) == LBER_ERROR)
  674. {
  675. goto loser;
  676. }
  677. slapi_entry_set_dn(e, str);
  678. str = NULL; /* Slapi_Entry now owns the dn */
  679. /* Get the attributes */
  680. for ( tag = ber_first_element( tmp_bere, &len, &lasto );
  681. tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET;
  682. tag = ber_next_element( tmp_bere, &len, lasto ) )
  683. {
  684. if (my_ber_scanf_attr (tmp_bere, &attr, &deleted) != 0)
  685. {
  686. goto loser;
  687. }
  688. /* Add the attribute to the entry */
  689. if (deleted)
  690. entry_add_deleted_attribute_wsi(e, attr); /* entry now owns attr */
  691. else
  692. entry_add_present_attribute_wsi(e, attr); /* entry now owns attr */
  693. attr = NULL;
  694. }
  695. if (ber_scanf(tmp_bere, "}") == LBER_ERROR) /* End sequence for this entry */
  696. {
  697. goto loser;
  698. }
  699. /* Check for ldapsubentries and tombstone entries to set flags properly */
  700. slapi_entry_attr_find(e, "objectclass", &attr);
  701. if (attr != NULL) {
  702. struct berval bv;
  703. bv.bv_val = "ldapsubentry";
  704. bv.bv_len = strlen(bv.bv_val);
  705. if (slapi_attr_value_find(attr, &bv) == 0) {
  706. slapi_entry_set_flag(e, SLAPI_ENTRY_LDAPSUBENTRY);
  707. }
  708. bv.bv_val = SLAPI_ATTR_VALUE_TOMBSTONE;
  709. bv.bv_len = strlen(bv.bv_val);
  710. if (slapi_attr_value_find(attr, &bv) == 0) {
  711. slapi_entry_set_flag(e, SLAPI_ENTRY_FLAG_TOMBSTONE);
  712. }
  713. }
  714. /* If we get here, the entry is properly constructed. Return it. */
  715. rc = 0;
  716. *ep = e;
  717. goto free_and_return;
  718. loser:
  719. rc = -1;
  720. /* slapi_ch_free accepts NULL pointer */
  721. slapi_ch_free((void **)&str);
  722. if (NULL != dn_csn)
  723. {
  724. csn_free(&dn_csn);
  725. }
  726. if (attr != NULL)
  727. {
  728. slapi_attr_free (&attr);
  729. }
  730. if (NULL != e)
  731. {
  732. slapi_entry_free (e);
  733. }
  734. *ep = NULL;
  735. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Error: could not decode extended "
  736. "operation containing entry for total update.\n");
  737. free_and_return:
  738. if (NULL != tmp_bere)
  739. {
  740. ber_free(tmp_bere, 1);
  741. tmp_bere = NULL;
  742. }
  743. return rc;
  744. }
  745. /*
  746. * This plugin entry point is called whenever an NSDS50ReplicationEntry
  747. * extended operation is received.
  748. */
  749. int
  750. multimaster_extop_NSDS50ReplicationEntry(Slapi_PBlock *pb)
  751. {
  752. int rc;
  753. Slapi_Entry *e = NULL;
  754. Slapi_Connection *conn = NULL;
  755. PRUint64 connid = 0;
  756. int opid = 0;
  757. slapi_pblock_get(pb, SLAPI_CONN_ID, &connid);
  758. slapi_pblock_get(pb, SLAPI_OPERATION_ID, &opid);
  759. /* Decode the extended operation */
  760. rc = decode_total_update_extop(pb, &e);
  761. if (0 == rc)
  762. {
  763. #ifdef notdef
  764. /*
  765. * Just spew LDIF so we're sure we got it right. Later we'll firehose
  766. * this into the database import code
  767. */
  768. int len;
  769. char *str = slapi_entry2str_with_options(e, &len,SLAPI_DUMP_UNIQUEID);
  770. puts(str);
  771. free(str);
  772. #endif
  773. rc = slapi_import_entry (pb, e);
  774. /* slapi_import_entry returns an LDAP error in case of a
  775. * problem. If there's a problem, it's our responsibility
  776. * to free the slapi_entry that we're trying to import.
  777. */
  778. if (rc != LDAP_SUCCESS)
  779. {
  780. const char *dn = slapi_entry_get_dn_const(e);
  781. slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
  782. "Error %d: could not import entry dn %s "
  783. "for total update operation conn=%" NSPRIu64 " op=%d\n",
  784. rc, dn, connid, opid);
  785. rc = -1;
  786. }
  787. }
  788. else
  789. {
  790. slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
  791. "Error %d: could not decode the total update extop "
  792. "for total update operation conn=%" NSPRIu64 " op=%d\n",
  793. rc, connid, opid);
  794. }
  795. if (rc != 0)
  796. {
  797. /* just disconnect from the supplier. bulk import is stopped when
  798. connection object is destroyed */
  799. slapi_pblock_get (pb, SLAPI_CONNECTION, &conn);
  800. if (conn)
  801. {
  802. slapi_disconnect_server(conn);
  803. }
  804. /* cleanup */
  805. if (e)
  806. {
  807. slapi_entry_free (e);
  808. }
  809. }
  810. return rc;
  811. }