repl5_total.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  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, char **excluded_attrs)
  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. /* Check to see if this attribute is excluded by the fractional list */
  138. if ( (NULL == excluded_attrs) || !charray_inlist(excluded_attrs,type))
  139. {
  140. /* Process this attribute */
  141. rc = my_ber_printf_attr (ber, attr, PR_FALSE);
  142. if (rc != 0)
  143. {
  144. goto loser;
  145. }
  146. }
  147. }
  148. prev_attr = attr;
  149. slapi_entry_next_attr(e, prev_attr, &attr);
  150. }
  151. /*
  152. * Now iterate over the deleted attributes.
  153. */
  154. entry_first_deleted_attribute(e, &attr);
  155. while (attr != NULL)
  156. {
  157. slapi_attr_get_type (attr, &type);
  158. /* Check to see if this attribute is excluded by the fractional list */
  159. if ( (NULL == excluded_attrs) || !charray_inlist(excluded_attrs,type))
  160. {
  161. /* Process this attribute */
  162. rc = my_ber_printf_attr (ber, attr, PR_TRUE);
  163. if (rc != 0)
  164. {
  165. goto loser;
  166. }
  167. }
  168. entry_next_deleted_attribute(e, &attr);
  169. }
  170. BER_DEBUG("]");
  171. if (ber_printf(ber, "]") == -1) /* End set for attributes */
  172. {
  173. goto loser;
  174. }
  175. BER_DEBUG("}");
  176. if (ber_printf(ber, "}") == -1) /* End sequence for this entry */
  177. {
  178. goto loser;
  179. }
  180. /* If we get here, everything went ok */
  181. BER_DEBUG("\n");
  182. goto free_and_return;
  183. loser:
  184. if (NULL != ber)
  185. {
  186. ber_free(ber, 1);
  187. ber = NULL;
  188. }
  189. free_and_return:
  190. return ber;
  191. }
  192. /*
  193. * Helper function - convert a CSN to a string and ber_printf() it.
  194. */
  195. static int
  196. my_ber_printf_csn(BerElement *ber, const CSN *csn, const CSNType t)
  197. {
  198. char csn_str[CSN_STRSIZE];
  199. unsigned long len;
  200. int rc = -1;
  201. int csn_type_as_ber = -1;
  202. switch (t)
  203. {
  204. case CSN_TYPE_VALUE_UPDATED:
  205. csn_type_as_ber = CSN_TYPE_VALUE_UPDATED_ON_WIRE;
  206. break;
  207. case CSN_TYPE_VALUE_DELETED:
  208. csn_type_as_ber = CSN_TYPE_VALUE_DELETED_ON_WIRE;
  209. break;
  210. case CSN_TYPE_VALUE_DISTINGUISHED:
  211. csn_type_as_ber = CSN_TYPE_VALUE_DISTINGUISHED_ON_WIRE;
  212. break;
  213. case CSN_TYPE_ATTRIBUTE_DELETED:
  214. break;
  215. default:
  216. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_printf_csn: unknown "
  217. "csn type %d encountered.\n", (int)t);
  218. return -1;
  219. }
  220. csn_as_string(csn,PR_FALSE,csn_str);
  221. /* we don't send type for attr csn since there is only one */
  222. if (t == CSN_TYPE_ATTRIBUTE_DELETED)
  223. {
  224. rc = ber_printf(ber, "s", csn_str);
  225. BER_DEBUG("s(csn_str)");
  226. }
  227. else
  228. {
  229. len = CSN_STRSIZE;
  230. rc = ber_printf(ber, "{es}", csn_type_as_ber, csn_str);
  231. BER_DEBUG("{e(csn type)s(csn)}");
  232. }
  233. return rc;
  234. }
  235. /*
  236. * Send a single annotated attribute value.
  237. */
  238. static int
  239. my_ber_printf_value(BerElement *ber, const char *type, const Slapi_Value *value, PRBool deleted)
  240. {
  241. const struct berval *bval = NULL;
  242. int rc = -1;
  243. const CSNSet *csnset;
  244. void *cookie;
  245. CSN *csn;
  246. CSNType t;
  247. bval = slapi_value_get_berval(value);
  248. BER_DEBUG("{o(value)");
  249. if (ber_printf(ber, "{o", bval->bv_val, bval->bv_len) == -1) /* Start sequence */
  250. {
  251. goto done;
  252. }
  253. /* if (ber_printf(ber, "o", bval->bv_val, bval->bv_len) == -1)
  254. {
  255. goto done;
  256. } */
  257. if (deleted)
  258. {
  259. BER_DEBUG("b(deleted flag)");
  260. if (ber_printf (ber, "b", PR_TRUE) == -1)
  261. {
  262. goto done;
  263. }
  264. }
  265. /* Send value CSN list */
  266. BER_DEBUG("{");
  267. if (ber_printf(ber, "{") == -1) /* Start set */
  268. {
  269. goto done;
  270. }
  271. /* Iterate over the sequence of CSNs. */
  272. csnset = value_get_csnset (value);
  273. if (csnset)
  274. {
  275. for (cookie = csnset_get_first_csn (csnset, &csn, &t); NULL != cookie;
  276. cookie = csnset_get_next_csn (csnset, cookie, &csn, &t))
  277. {
  278. /* Don't send any adcsns, since that was already sent */
  279. if (t != CSN_TYPE_ATTRIBUTE_DELETED)
  280. {
  281. if (my_ber_printf_csn(ber, csn, t) == -1)
  282. {
  283. goto done;
  284. }
  285. }
  286. }
  287. }
  288. BER_DEBUG("}");
  289. if (ber_printf(ber, "}") == -1) /* End CSN sequence */
  290. {
  291. goto done;
  292. }
  293. BER_DEBUG("}");
  294. if (ber_printf(ber, "}") == -1) /* End sequence */
  295. {
  296. goto done;
  297. }
  298. /* Everything's ok */
  299. rc = 0;
  300. done:
  301. return rc;
  302. }
  303. /* send a single attribute */
  304. static int
  305. my_ber_printf_attr (BerElement *ber, Slapi_Attr *attr, PRBool deleted)
  306. {
  307. Slapi_Value *value;
  308. char *type;
  309. int i;
  310. const CSN *csn;
  311. /* First, send the type */
  312. slapi_attr_get_type(attr, &type);
  313. BER_DEBUG("{s(type ");
  314. BER_DEBUG(type);
  315. BER_DEBUG(")");
  316. if (ber_printf(ber, "{s", type) == -1) /* Begin sequence for this type */
  317. {
  318. goto loser;
  319. }
  320. /* Send the attribute deletion CSN if present */
  321. csn = attr_get_deletion_csn(attr);
  322. if (csn)
  323. {
  324. if (my_ber_printf_csn(ber, csn, CSN_TYPE_ATTRIBUTE_DELETED) == -1)
  325. {
  326. goto loser;
  327. }
  328. }
  329. /* only send "is deleted" flag for deleted attributes since it defaults to false */
  330. if (deleted)
  331. {
  332. BER_DEBUG("b(del flag)");
  333. if (ber_printf (ber, "b", PR_TRUE) == -1)
  334. {
  335. goto loser;
  336. }
  337. }
  338. /*
  339. * Iterate through all the values.
  340. */
  341. BER_DEBUG("[");
  342. if (ber_printf(ber, "[") == -1) /* Begin set */
  343. {
  344. goto loser;
  345. }
  346. /*
  347. * Process the non-deleted values first.
  348. */
  349. i = slapi_attr_first_value(attr, &value);
  350. while (i != -1)
  351. {
  352. if (my_ber_printf_value(ber, type, value, PR_FALSE) == -1)
  353. {
  354. goto loser;
  355. }
  356. i= slapi_attr_next_value(attr, i, &value);
  357. }
  358. /*
  359. * Now iterate over all of the deleted values.
  360. */
  361. i= attr_first_deleted_value(attr, &value);
  362. while (i != -1)
  363. {
  364. if (my_ber_printf_value(ber, type, value, PR_TRUE) == -1)
  365. {
  366. goto loser;
  367. }
  368. i= attr_next_deleted_value(attr, i, &value);
  369. }
  370. BER_DEBUG("]");
  371. if (ber_printf(ber, "]") == -1) /* End set */
  372. {
  373. goto loser;
  374. }
  375. BER_DEBUG("}");
  376. if (ber_printf(ber, "}") == -1) /* End sequence for this type */
  377. {
  378. goto loser;
  379. }
  380. return 0;
  381. loser:
  382. return -1;
  383. }
  384. /*
  385. * Get an annotated value from the BerElement. Returns 0 on
  386. * success, -1 on failure.
  387. */
  388. static int
  389. my_ber_scanf_value(BerElement *ber, Slapi_Value **value, PRBool *deleted)
  390. {
  391. struct berval *attrval = NULL;
  392. unsigned long len;
  393. unsigned long tag;
  394. CSN *csn = NULL;
  395. char csnstring[CSN_STRSIZE + 1];
  396. CSNType csntype;
  397. char *lasti;
  398. PR_ASSERT(ber && value && deleted);
  399. *value = NULL;
  400. if (NULL == ber && NULL == value)
  401. {
  402. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 1\n");
  403. goto loser;
  404. }
  405. /* Each value is a sequence */
  406. if (ber_scanf(ber, "{O", &attrval) == -1)
  407. {
  408. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 2\n");
  409. goto loser;
  410. }
  411. /* Allocate and fill in the attribute value */
  412. if ((*value = slapi_value_new_berval(attrval)) == NULL)
  413. {
  414. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 3\n");
  415. goto loser;
  416. }
  417. /* check if this is a deleted value */
  418. if (ber_peek_tag(ber, &len) == LBER_BOOLEAN)
  419. {
  420. if (ber_scanf(ber, "b", deleted) == -1)
  421. {
  422. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 4\n");
  423. goto loser;
  424. }
  425. }
  426. else /* default is present value */
  427. {
  428. *deleted = PR_FALSE;
  429. }
  430. /* Read the sequence of CSNs */
  431. for (tag = ber_first_element(ber, &len, &lasti);
  432. tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET;
  433. tag = ber_next_element(ber, &len, lasti))
  434. {
  435. long csntype_tmp;
  436. /* Each CSN is in a sequence that includes a csntype and CSN */
  437. len = CSN_STRSIZE;
  438. if (ber_scanf(ber, "{es}", &csntype_tmp, csnstring, &len) == -1)
  439. {
  440. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 7 - bval is %s\n", attrval->bv_val);
  441. goto loser;
  442. }
  443. switch (csntype_tmp)
  444. {
  445. case CSN_TYPE_VALUE_UPDATED_ON_WIRE:
  446. csntype = CSN_TYPE_VALUE_UPDATED;
  447. break;
  448. case CSN_TYPE_VALUE_DELETED_ON_WIRE:
  449. csntype = CSN_TYPE_VALUE_DELETED;
  450. break;
  451. case CSN_TYPE_VALUE_DISTINGUISHED_ON_WIRE:
  452. csntype = CSN_TYPE_VALUE_DISTINGUISHED;
  453. break;
  454. default:
  455. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Error: preposterous CSN type "
  456. "%d received during total update.\n", csntype_tmp);
  457. goto loser;
  458. }
  459. csn = csn_new_by_string(csnstring);
  460. if (csn == NULL)
  461. {
  462. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 8\n");
  463. goto loser;
  464. }
  465. value_add_csn(*value, csntype, csn);
  466. csn_free (&csn);
  467. }
  468. if (ber_scanf(ber, "}") == -1) /* End of annotated attribute value seq */
  469. {
  470. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 10\n");
  471. goto loser;
  472. }
  473. if (attrval)
  474. ber_bvfree(attrval);
  475. return 0;
  476. loser:
  477. /* Free any stuff we allocated */
  478. if (csn)
  479. csn_free (&csn);
  480. if (attrval)
  481. ber_bvfree(attrval);
  482. if (value)
  483. {
  484. slapi_value_free (value);
  485. }
  486. return -1;
  487. }
  488. static int
  489. my_ber_scanf_attr (BerElement *ber, Slapi_Attr **attr, PRBool *deleted)
  490. {
  491. char *attrtype = NULL;
  492. CSN *attr_deletion_csn = NULL;
  493. PRBool val_deleted;
  494. char *lasti;
  495. unsigned long len;
  496. unsigned long tag;
  497. char *str;
  498. int rc;
  499. Slapi_Value *value;
  500. PR_ASSERT (ber && attr && deleted);
  501. /* allocate the attribute */
  502. *attr = slapi_attr_new ();
  503. if (attr == NULL)
  504. {
  505. goto loser;
  506. }
  507. if (ber_scanf(ber, "{a", &attrtype) == -1) /* Begin sequence for this attr */
  508. {
  509. goto loser;
  510. }
  511. slapi_attr_init(*attr, attrtype);
  512. slapi_ch_free ((void **)&attrtype);
  513. /* The attribute deletion CSN is next and is optional? */
  514. if (ber_peek_tag(ber, &len) == LBER_OCTETSTRING)
  515. {
  516. if (ber_scanf(ber, "a", &str) == -1)
  517. {
  518. goto loser;
  519. }
  520. attr_deletion_csn = csn_new_by_string(str);
  521. slapi_ch_free((void **)&str);
  522. }
  523. if (attr_deletion_csn)
  524. {
  525. rc = attr_set_deletion_csn(*attr, attr_deletion_csn);
  526. csn_free (&attr_deletion_csn);
  527. if (rc != 0)
  528. {
  529. goto loser;
  530. }
  531. }
  532. /* The "attribute deleted" flag is next, and is optional */
  533. if (ber_peek_tag(ber, &len) == LBER_BOOLEAN)
  534. {
  535. if (ber_scanf(ber, "b", deleted) == -1)
  536. {
  537. goto loser;
  538. }
  539. }
  540. else /* default is present */
  541. {
  542. *deleted = PR_FALSE;
  543. }
  544. /* loop over the list of attribute values */
  545. for (tag = ber_first_element(ber, &len, &lasti);
  546. tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET;
  547. tag = ber_next_element(ber, &len, lasti))
  548. {
  549. value = NULL;
  550. if (my_ber_scanf_value(ber, &value, &val_deleted) == -1)
  551. {
  552. goto loser;
  553. }
  554. if (val_deleted)
  555. {
  556. /* Add the value to the attribute */
  557. if (attr_add_deleted_value(*attr, value) == -1) /* attr has ownership of value */
  558. {
  559. goto loser;
  560. }
  561. }
  562. else
  563. {
  564. /* Add the value to the attribute */
  565. if (slapi_attr_add_value(*attr, value) == -1) /* attr has ownership of value */
  566. {
  567. goto loser;
  568. }
  569. }
  570. if (value)
  571. slapi_value_free(&value);
  572. }
  573. if (ber_scanf(ber, "}") == -1) /* End sequence for this attribute */
  574. {
  575. goto loser;
  576. }
  577. return 0;
  578. loser:
  579. if (*attr)
  580. slapi_attr_free (attr);
  581. if (value)
  582. slapi_value_free (&value);
  583. return -1;
  584. }
  585. /*
  586. * Extract the payload from a total update extended operation,
  587. * decode it, and produce a Slapi_Entry structure representing a new
  588. * entry to be added to the local database.
  589. */
  590. static int
  591. decode_total_update_extop(Slapi_PBlock *pb, Slapi_Entry **ep)
  592. {
  593. BerElement *tmp_bere = NULL;
  594. Slapi_Entry *e = NULL;
  595. Slapi_Attr *attr = NULL;
  596. char *str = NULL;
  597. CSN *dn_csn = NULL;
  598. struct berval *extop_value = NULL;
  599. char *extop_oid = NULL;
  600. unsigned long len;
  601. char *lasto;
  602. unsigned long tag;
  603. int rc;
  604. PRBool deleted;
  605. PR_ASSERT(NULL != pb);
  606. PR_ASSERT(NULL != ep);
  607. slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_OID, &extop_oid);
  608. slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_value);
  609. if (NULL == extop_oid ||
  610. ((strcmp(extop_oid, REPL_NSDS50_REPLICATION_ENTRY_REQUEST_OID) != 0) &&
  611. (strcmp(extop_oid, REPL_NSDS71_REPLICATION_ENTRY_REQUEST_OID) != 0)) ||
  612. NULL == extop_value)
  613. {
  614. /* Bogus */
  615. goto loser;
  616. }
  617. if ((tmp_bere = ber_init(extop_value)) == NULL)
  618. {
  619. goto loser;
  620. }
  621. if ((e = slapi_entry_alloc()) == NULL)
  622. {
  623. goto loser;
  624. }
  625. if (ber_scanf(tmp_bere, "{") == -1) /* Begin outer sequence */
  626. {
  627. goto loser;
  628. }
  629. /* The entry's uniqueid is first */
  630. if (ber_scanf(tmp_bere, "a", &str) == -1)
  631. {
  632. goto loser;
  633. }
  634. slapi_entry_set_uniqueid(e, str);
  635. str = NULL; /* Slapi_Entry now owns the uniqueid */
  636. /* The entry's DN is next */
  637. if (ber_scanf(tmp_bere, "a", &str) == -1)
  638. {
  639. goto loser;
  640. }
  641. slapi_entry_set_dn(e, str);
  642. str = NULL; /* Slapi_Entry now owns the dn */
  643. /* Get the attributes */
  644. for ( tag = ber_first_element( tmp_bere, &len, &lasto );
  645. tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET;
  646. tag = ber_next_element( tmp_bere, &len, lasto ) )
  647. {
  648. if (my_ber_scanf_attr (tmp_bere, &attr, &deleted) != 0)
  649. {
  650. goto loser;
  651. }
  652. /* Add the attribute to the entry */
  653. if (deleted)
  654. entry_add_deleted_attribute_wsi(e, attr); /* entry now owns attr */
  655. else
  656. entry_add_present_attribute_wsi(e, attr); /* entry now owns attr */
  657. attr = NULL;
  658. }
  659. if (ber_scanf(tmp_bere, "}") == -1) /* End sequence for this entry */
  660. {
  661. goto loser;
  662. }
  663. /* Check for ldapsubentries and tombstone entries to set flags properly */
  664. slapi_entry_attr_find(e, "objectclass", &attr);
  665. if (attr != NULL) {
  666. struct berval bv;
  667. bv.bv_val = "ldapsubentry";
  668. bv.bv_len = strlen(bv.bv_val);
  669. if (slapi_attr_value_find(attr, &bv) == 0) {
  670. slapi_entry_set_flag(e, SLAPI_ENTRY_LDAPSUBENTRY);
  671. }
  672. bv.bv_val = SLAPI_ATTR_VALUE_TOMBSTONE;
  673. bv.bv_len = strlen(bv.bv_val);
  674. if (slapi_attr_value_find(attr, &bv) == 0) {
  675. slapi_entry_set_flag(e, SLAPI_ENTRY_FLAG_TOMBSTONE);
  676. }
  677. }
  678. /* If we get here, the entry is properly constructed. Return it. */
  679. rc = 0;
  680. *ep = e;
  681. goto free_and_return;
  682. loser:
  683. rc = -1;
  684. /* slapi_ch_free accepts NULL pointer */
  685. slapi_ch_free((void **)&str);
  686. if (NULL != dn_csn)
  687. {
  688. csn_free(&dn_csn);
  689. }
  690. if (attr != NULL)
  691. {
  692. slapi_attr_free (&attr);
  693. }
  694. if (NULL != e)
  695. {
  696. slapi_entry_free (e);
  697. }
  698. *ep = NULL;
  699. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Error: could not decode extended "
  700. "operation containing entry for total update.\n");
  701. free_and_return:
  702. if (NULL != tmp_bere)
  703. {
  704. ber_free(tmp_bere, 1);
  705. tmp_bere = NULL;
  706. }
  707. return rc;
  708. }
  709. /*
  710. * This plugin entry point is called whenever an NSDS50ReplicationEntry
  711. * extended operation is received.
  712. */
  713. int
  714. multimaster_extop_NSDS50ReplicationEntry(Slapi_PBlock *pb)
  715. {
  716. int rc;
  717. Slapi_Entry *e = NULL;
  718. Slapi_Connection *conn = NULL;
  719. int connid, opid;
  720. connid = 0;
  721. slapi_pblock_get(pb, SLAPI_CONN_ID, &connid);
  722. opid = 0;
  723. slapi_pblock_get(pb, SLAPI_OPERATION_ID, &opid);
  724. /* Decode the extended operation */
  725. rc = decode_total_update_extop(pb, &e);
  726. if (0 == rc)
  727. {
  728. #ifdef notdef
  729. /*
  730. * Just spew LDIF so we're sure we got it right. Later we'll firehose
  731. * this into the database import code
  732. */
  733. int len;
  734. char *str = slapi_entry2str_with_options(e, &len,SLAPI_DUMP_UNIQUEID);
  735. puts(str);
  736. free(str);
  737. #endif
  738. rc = slapi_import_entry (pb, e);
  739. /* slapi_import_entry return an LDAP error in case of problem
  740. * LDAP_BUSY is used to indicate that the import queue is full
  741. * and that flow control must happen to stop the supplier
  742. * from sending entries
  743. */
  744. if ((rc != LDAP_SUCCESS) && (rc != LDAP_BUSY))
  745. {
  746. const char *dn = slapi_entry_get_dn_const(e);
  747. slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
  748. "Error %d: could not import entry dn %s "
  749. "for total update operation conn=%d op=%d\n",
  750. rc, dn, connid, opid);
  751. rc = -1;
  752. }
  753. }
  754. else
  755. {
  756. slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
  757. "Error %d: could not decode the total update extop "
  758. "for total update operation conn=%d op=%d\n",
  759. rc, connid, opid);
  760. }
  761. if ((rc != 0) && (rc != LDAP_BUSY))
  762. {
  763. /* just disconnect from the supplier. bulk import is stopped when
  764. connection object is destroyed */
  765. slapi_pblock_get (pb, SLAPI_CONNECTION, &conn);
  766. if (conn)
  767. {
  768. slapi_disconnect_server(conn);
  769. }
  770. /* cleanup */
  771. if (e)
  772. {
  773. slapi_entry_free (e);
  774. }
  775. }
  776. return rc;
  777. }