repl5_total.c 20 KB

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